fix: brainstorm infinite loop, ghost cursor, embedding ::vector cast, semantic search, billing stats, usage meter accordion
All checks were successful
Deploy to Production / Build and Deploy (push) Successful in 5s

- Fix useBrainstormSocket: stable guestId via useRef, remove setState in cleanup
- Fix GhostCursor: direct DOM manipulation via refs, no useState re-renders
- Fix all SQL embedding queries: add ::vector cast on text columns
- Fix embedding truncation to 15000 chars (under 8192 token limit)
- Fix NoteEmbedding INSERT: remove non-existent updatedAt column
- Fix billing page: show all quota stats in grid instead of single metric
- Fix usage meter: accordion expand/collapse, per-feature detail
- Fix semantic search: rebuild 103 note embeddings, ::vector cast on vectorSearch
- Fix brainstorm expand/manual-idea/create: ::vector cast on embedding SQL
This commit is contained in:
Antigravity
2026-05-16 18:50:34 +00:00
parent ee8e2bda59
commit 8c7ca69640
117 changed files with 11732 additions and 834 deletions

View File

@@ -1,21 +1,103 @@
'use client'
import { useState } from 'react'
import { useState, useRef, useEffect, useCallback } from 'react'
import { createPortal } from 'react-dom'
import { Button } from '@/components/ui/button'
import { deleteUser, updateUserRole } from '@/app/actions/admin'
import { deleteUser, updateUserRole, updateUserSubscription } from '@/app/actions/admin'
import { toast } from 'sonner'
import { Trash2, Shield, ShieldOff } from 'lucide-react'
import { Trash2, Shield, ShieldOff, Crown, ChevronDown } from 'lucide-react'
import { format } from 'date-fns'
import { useLanguage } from '@/lib/i18n'
const TIERS = ['BASIC', 'PRO', 'BUSINESS', 'ENTERPRISE'] as const
const tierColors: Record<string, string> = {
BASIC: 'bg-gray-100 text-gray-700 dark:bg-gray-800 dark:text-gray-300',
PRO: 'bg-brand-accent/10 text-brand-accent',
BUSINESS: 'bg-blue-50 text-blue-700 dark:bg-blue-900/30 dark:text-blue-400',
ENTERPRISE: 'bg-purple-50 text-purple-700 dark:bg-purple-900/30 dark:text-purple-400',
}
function TierDropdown({ userId, tier, isOpen, onToggle, onClose, onChange }: {
userId: string
tier: string
isOpen: boolean
onToggle: () => void
onClose: () => void
onChange: (tier: string) => void
}) {
const btnRef = useRef<HTMLButtonElement>(null)
const [pos, setPos] = useState({ top: 0, left: 0 })
const updatePos = useCallback(() => {
if (btnRef.current) {
const r = btnRef.current.getBoundingClientRect()
setPos({ top: r.bottom + 4, left: r.left })
}
}, [])
useEffect(() => {
if (isOpen) {
updatePos()
window.addEventListener('scroll', updatePos, true)
window.addEventListener('resize', updatePos)
}
return () => {
window.removeEventListener('scroll', updatePos, true)
window.removeEventListener('resize', updatePos)
}
}, [isOpen, updatePos])
return (
<td className="p-4 align-middle">
<button
ref={btnRef}
onClick={(e) => { e.stopPropagation(); onToggle() }}
className={`inline-flex items-center gap-1.5 rounded-full px-2.5 py-0.5 text-xs font-semibold transition-colors cursor-pointer hover:opacity-80 ${tierColors[tier] || tierColors.BASIC}`}
>
{tier === 'ENTERPRISE' && <Crown size={10} />}
{tier}
<ChevronDown size={10} />
</button>
{isOpen && typeof document !== 'undefined' && createPortal(
<>
<div className="fixed inset-0 z-[9998]" onClick={onClose} />
<div
className="fixed z-[9999] bg-white dark:bg-zinc-900 border border-border rounded-xl shadow-xl py-1 min-w-[140px]"
style={{ top: pos.top, left: pos.left }}
>
{TIERS.map((t) => (
<button
key={t}
onClick={(e) => { e.stopPropagation(); onChange(t) }}
className={`w-full text-left px-4 py-2 text-xs font-medium transition-colors hover:bg-muted flex items-center gap-2 ${tier === t ? 'text-brand-accent font-bold' : 'text-foreground'}`}
>
{tier === t && '✓'}
<span className={`inline-flex items-center gap-1 ${tier === t ? '' : 'ml-4'}`}>
{t === 'ENTERPRISE' && <Crown size={10} />}
{t}
</span>
</button>
))}
</div>
</>,
document.body
)}
</td>
)
}
export function UserList({ initialUsers }: { initialUsers: any[] }) {
const { t } = useLanguage()
const [users, setUsers] = useState(initialUsers)
const [openDropdown, setOpenDropdown] = useState<string | null>(null)
const handleDelete = async (id: string) => {
if (!confirm(t('admin.users.confirmDelete'))) return
try {
await deleteUser(id)
toast.success(t('admin.users.deleteSuccess'))
setUsers(prev => prev.filter(u => u.id !== id))
} catch (e) {
toast.error(t('admin.users.deleteFailed'))
}
@@ -26,11 +108,25 @@ export function UserList({ initialUsers }: { initialUsers: any[] }) {
try {
await updateUserRole(user.id, newRole)
toast.success(t('admin.users.roleUpdateSuccess', { role: newRole }))
setUsers(prev => prev.map(u => u.id === user.id ? { ...u, role: newRole } : u))
} catch (e) {
toast.error(t('admin.users.roleUpdateFailed'))
}
}
const handleTierChange = async (userId: string, tier: string) => {
setOpenDropdown(null)
try {
await updateUserSubscription(userId, tier)
toast.success(t('admin.users.tierUpdateSuccess', { tier }))
setUsers(prev => prev.map(u => u.id === userId ? { ...u, subscription: { tier, status: 'ACTIVE' } } : u))
} catch (e) {
toast.error(t('admin.users.tierUpdateFailed'))
}
}
const getUserTier = (user: any) => user.subscription?.tier || 'BASIC'
return (
<div className="w-full overflow-auto">
<table className="w-full caption-bottom text-sm text-left">
@@ -39,43 +135,55 @@ export function UserList({ initialUsers }: { initialUsers: any[] }) {
<th className="h-12 px-4 align-middle font-medium text-muted-foreground">{t('admin.users.table.name')}</th>
<th className="h-12 px-4 align-middle font-medium text-muted-foreground">{t('admin.users.table.email')}</th>
<th className="h-12 px-4 align-middle font-medium text-muted-foreground">{t('admin.users.table.role')}</th>
<th className="h-12 px-4 align-middle font-medium text-muted-foreground">{t('admin.users.table.subscription') || 'Abonnement'}</th>
<th className="h-12 px-4 align-middle font-medium text-muted-foreground">{t('admin.users.table.createdAt')}</th>
<th className="h-12 px-4 align-middle font-medium text-muted-foreground text-right">{t('admin.users.table.actions')}</th>
</tr>
</thead>
<tbody className="[&_tr:last-child]:border-0">
{initialUsers.map((user) => (
<tr key={user.id} className="border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted">
<td className="p-4 align-middle font-medium">{user.name || t('common.notAvailable')}</td>
<td className="p-4 align-middle">{user.email}</td>
<td className="p-4 align-middle">
<span className={`inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 ${user.role === 'ADMIN' ? 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80' : 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80'}`}>
{user.role === 'ADMIN' ? t('admin.users.roles.admin') : t('admin.users.roles.user')}
</span>
</td>
<td className="p-4 align-middle">{format(new Date(user.createdAt), 'PP')}</td>
<td className="p-4 align-middle text-right">
<div className="flex justify-end gap-2">
<Button
variant="ghost"
size="sm"
onClick={() => handleRoleToggle(user)}
title={user.role === 'ADMIN' ? t('admin.users.demote') : t('admin.users.promote')}
>
{user.role === 'ADMIN' ? <ShieldOff className="h-4 w-4" /> : <Shield className="h-4 w-4" />}
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => handleDelete(user.id)}
className="text-red-600 hover:text-red-900"
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
</td>
</tr>
))}
{users.map((user) => {
const tier = getUserTier(user)
return (
<tr key={user.id} className="border-b transition-colors hover:bg-muted/50 data-[state=selected]:bg-muted">
<td className="p-4 align-middle font-medium">{user.name || t('common.notAvailable')}</td>
<td className="p-4 align-middle">{user.email}</td>
<td className="p-4 align-middle">
<span className={`inline-flex items-center rounded-full border px-2.5 py-0.5 text-xs font-semibold transition-colors focus:outline-none focus:ring-2 focus:ring-ring focus:ring-offset-2 ${user.role === 'ADMIN' ? 'border-transparent bg-primary text-primary-foreground hover:bg-primary/80' : 'border-transparent bg-secondary text-secondary-foreground hover:bg-secondary/80'}`}>
{user.role === 'ADMIN' ? t('admin.users.roles.admin') : t('admin.users.roles.user')}
</span>
</td>
<TierDropdown
userId={user.id}
tier={tier}
isOpen={openDropdown === user.id}
onToggle={() => setOpenDropdown(openDropdown === user.id ? null : user.id)}
onClose={() => setOpenDropdown(null)}
onChange={(t) => handleTierChange(user.id, t)}
/>
<td className="p-4 align-middle">{format(new Date(user.createdAt), 'PP')}</td>
<td className="p-4 align-middle text-right">
<div className="flex justify-end gap-2">
<Button
variant="ghost"
size="sm"
onClick={() => handleRoleToggle(user)}
title={user.role === 'ADMIN' ? t('admin.users.demote') : t('admin.users.promote')}
>
{user.role === 'ADMIN' ? <ShieldOff className="h-4 w-4" /> : <Shield className="h-4 w-4" />}
</Button>
<Button
variant="ghost"
size="sm"
onClick={() => handleDelete(user.id)}
className="text-red-600 hover:text-red-900"
>
<Trash2 className="h-4 w-4" />
</Button>
</div>
</td>
</tr>
)
})}
</tbody>
</table>
</div>

View File

@@ -2,7 +2,7 @@
import { useState, useCallback, useMemo, useEffect, useRef } from 'react'
import { motion } from 'motion/react'
import { PageEntry } from '@/components/page-entry'
import { Plus, Bot, Search, LifeBuoy } from 'lucide-react'
import { toast } from 'sonner'
import { useLanguage } from '@/lib/i18n'
@@ -205,7 +205,6 @@ export function AgentsPageClient({
const showDetail = selectedAgent !== null || isNewAgent
return (
<PageEntry>
<>
{showDetail ? (
<AgentDetailView
@@ -334,6 +333,5 @@ export function AgentsPageClient({
<AgentHelp onClose={() => setShowHelp(false)} />
)}
</>
</PageEntry>
)
}

View File

@@ -7,7 +7,7 @@ import { detectUserLanguage, parseAcceptLanguage } from "@/lib/i18n/detect-user-
import { loadTranslations } from "@/lib/i18n/load-translations";
import { getAISettings } from "@/app/actions/ai-settings";
import { AIChatLayoutBridge } from "@/components/ai-chat-layout-bridge";
import { PageTransition } from "@/components/page-transition";
export default async function MainLayout({
children,
@@ -38,9 +38,7 @@ export default async function MainLayout({
</Suspense>
<main className="flex min-h-0 flex-1 flex-col overflow-y-auto scroll-smooth bg-memento-paper dark:bg-background">
<PageTransition>
{children}
</PageTransition>
{children}
</main>
{showAIAssistant && <AIChatLayoutBridge />}

View File

@@ -7,7 +7,7 @@ import { toast } from 'sonner'
import { useRouter } from 'next/navigation'
import { Globe, Bell } from 'lucide-react'
import { motion } from 'motion/react'
import { PageEntry } from '@/components/page-entry'
interface GeneralSettingsClientProps {
initialSettings: {

View File

@@ -0,0 +1,16 @@
'use client'
import { motion } from 'motion/react'
export default function MainTemplate({ children }: { children: React.ReactNode }) {
return (
<motion.div
initial={{ opacity: 0, x: 20 }}
animate={{ opacity: 1, x: 0 }}
transition={{ duration: 0.3 }}
className="flex-1 flex flex-col min-h-0"
>
{children}
</motion.div>
)
}

View File

@@ -3,7 +3,7 @@
import { useState, useMemo } from 'react'
import { useRouter } from 'next/navigation'
import { motion, AnimatePresence } from 'motion/react'
import { PageEntry } from '@/components/page-entry'
import {
Trash2,
RotateCcw,
@@ -138,7 +138,6 @@ export function TrashClient({
}
return (
<PageEntry>
<div className="h-full flex flex-col bg-[#F9F8F6] dark:bg-[#1a1a1a]">
<header className="px-12 pt-12 pb-8 flex flex-col gap-6 sticky top-0 bg-[#F9F8F6]/80 dark:bg-[#1a1a1a]/80 backdrop-blur-md z-30 border-b border-border/20">
<div className="flex items-center justify-between">
@@ -289,6 +288,5 @@ export function TrashClient({
</p>
</footer>
</div>
</PageEntry>
)
}

View File

@@ -0,0 +1,17 @@
import { headers } from 'next/headers'
import { detectUserLanguage, parseAcceptLanguage } from '@/lib/i18n/detect-user-language'
import { loadTranslations } from '@/lib/i18n/load-translations'
import { PublicProviders } from '@/components/public-providers'
export default async function PublicLayout({ children }: { children: React.ReactNode }) {
const headersList = await headers()
const browserLang = parseAcceptLanguage(headersList.get('accept-language'))
const initialLanguage = await detectUserLanguage(browserLang)
const initialTranslations = await loadTranslations(initialLanguage)
return (
<PublicProviders initialLanguage={initialLanguage} initialTranslations={initialTranslations}>
{children}
</PublicProviders>
)
}

View File

@@ -0,0 +1,5 @@
import { LandingPage } from '@/components/landing-page'
export default function PublicHomePage() {
return <LandingPage />
}

View File

@@ -5,6 +5,7 @@ import prisma from '@/lib/prisma'
import { auth } from '@/auth'
import bcrypt from 'bcryptjs'
import { z } from 'zod'
import { SubscriptionTier, SubscriptionStatus } from '@prisma/client'
// Schema pour la création d'utilisateur
const CreateUserSchema = z.object({
@@ -33,6 +34,13 @@ export async function getUsers() {
email: true,
role: true,
createdAt: true,
subscription: {
select: {
tier: true,
status: true,
currentPeriodEnd: true,
}
}
}
})
return users
@@ -118,3 +126,39 @@ export async function updateUserRole(userId: string, newRole: string) {
throw new Error('Failed to update role')
}
}
export async function updateUserSubscription(userId: string, tier: string) {
await checkAdmin()
const validTiers: string[] = ['BASIC', 'PRO', 'BUSINESS', 'ENTERPRISE']
if (!validTiers.includes(tier)) {
throw new Error('Invalid tier')
}
try {
const now = new Date()
const periodEnd = new Date(now)
periodEnd.setFullYear(periodEnd.getFullYear() + 1)
await prisma.subscription.upsert({
where: { userId },
update: {
tier: tier as SubscriptionTier,
status: 'ACTIVE',
currentPeriodStart: now,
currentPeriodEnd: periodEnd,
},
create: {
userId,
tier: tier as SubscriptionTier,
status: 'ACTIVE' as SubscriptionStatus,
currentPeriodStart: now,
currentPeriodEnd: periodEnd,
},
})
revalidatePath('/admin')
return { success: true }
} catch (error) {
throw new Error('Failed to update subscription')
}
}

View File

@@ -11,7 +11,7 @@ export async function authenticate(
await signIn('credentials', {
email: formData.get('email'),
password: formData.get('password'),
redirectTo: '/',
redirectTo: '/home',
});
} catch (error) {
if (error instanceof AuthError) {

View File

@@ -128,7 +128,7 @@ export async function respondToBrainstormShare(
})
}
revalidatePath('/')
revalidatePath('/home')
return { success: true }
}
@@ -193,6 +193,6 @@ export async function removeBrainstormShare(sessionId: string) {
data: { status: 'removed' },
})
revalidatePath('/')
revalidatePath('/home')
return { success: true }
}

View File

@@ -3,7 +3,7 @@
import DOMPurify from 'isomorphic-dompurify'
import { auth } from '@/auth'
import { prisma } from '@/lib/prisma'
import { getAIProvider } from '@/lib/ai/factory'
import { getChatProvider } from '@/lib/ai/factory'
import { getSystemConfig } from '@/lib/config'
import { getAISettings } from '@/app/actions/ai-settings'
import { revalidatePath } from 'next/cache'
@@ -58,18 +58,47 @@ export async function generateNoteIllustrationSvg(noteId: string): Promise<{ ok:
}
const config = await getSystemConfig()
const provider = getAIProvider(config)
const provider = getChatProvider(config)
const prompt = `Tu es un designer minimaliste. Produis UN SEUL document SVG valide pour une vignette de carte note.
Contraintes strictes:
- viewBox="0 0 224 168" (rapport 4:3), pas de width/height fixes en px sur la racine ou width="100%" height="100%"
- Style architectural / papier, 24 formes géométriques ou lignes, palette sobre (noir/gris/une couleur douce), pas de texte lisible
- AUCUN script, AUCUNE balise foreignObject, AUCUN lien externe, AUCUN attribut on*
- Réponds UNIQUEMENT avec le fragment SVG (commence par <svg ...> et finit par </svg>), sans markdown ni commentaire.
const prompt = `Create a small SVG thumbnail that VISUALLY REPRESENTS this note's topic.
Thème à suggérer visuellement (abstrait, pas littéral):
Titre: ${plainTitle || '(sans titre)'}
Extrait: ${plainBody.slice(0, 400)}`
OUTPUT: Only raw SVG markup. No markdown, no code fences, no comments. Start with <svg and end with </svg>.
SPECIFICATIONS:
- viewBox="0 0 224 168", NO fixed width/height attributes
- Maximum 1000 bytes
- Background: soft warm beige (#F5F0E8) or transparent
- Color palette (pick 2-3): warm charcoal (#2C2C2C), slate gray (#6B7280), soft sage (#A8B5A0), muted ochre (#C4A882), dusty rose (#C9A9A6), teal (#5F9EA0), burgundy (#8B4513)
- NO text, NO scripts, NO foreignObject, NO external links
CRITICAL: The illustration MUST be recognizably related to the topic.
Think of it like an ICON or PICTOGRAM for the title. Not abstract random shapes.
TOPIC: "${plainTitle || 'untitled'}"
How to illustrate this topic (pick the BEST match):
- If the topic is about CODE/DEV: Show angle brackets <>, curly braces {}, a terminal window shape, or circuit-like lines
- If the topic is about MUSIC: Show sound waves, musical notes shapes, or speaker icon
- If the topic is about FOOD/COOKING: Show a pot shape, utensils, or plate
- If the topic is about TRAVEL: Show a path/road, mountain peaks, or compass
- If the topic is about SCIENCE: Show atom orbits, flask/beaker, or molecule bonds
- If the topic is about BUSINESS/FINANCE: Show ascending chart lines, coins, or briefcase
- If the topic is about HEALTH: Show heart shape, pulse line, or leaf
- If the topic is about EDUCATION: Show book shape, graduation cap, or pencil
- If the topic is about NATURE: Show tree, mountain, water wave, or sun
- If the topic is about DESIGN/ART: Show palette, brush stroke, or frame
- If the topic is about PEOPLE/TEAM: Show overlapping circles, handshake, or connected nodes
- If the topic is about ARCHITECTURE: Show building outline, blueprint grid, or columns
- Otherwise: Extract the KEY CONCEPT from the title and draw its SIMPLEST iconic representation
TECHNICAL RULES:
- Use simple shapes: <circle>, <rect>, <line>, <path>, <ellipse>, <polygon>, <g>
- Keep it FLAT and MINIMAL — 2-4 elements max
- Use opacity for depth (0.3-0.8)
- The icon should be immediately recognizable even at small size
Additional context from the note:
${plainBody.slice(0, 200)}`
const raw = await provider.generateText(prompt)
const extracted = extractSvgSnippet(raw)
@@ -90,7 +119,7 @@ Extrait: ${plainBody.slice(0, 400)}`
},
})
revalidatePath('/')
revalidatePath('/home')
return { ok: true }
} catch (e) {
console.error('[note-illustration]', e)

View File

@@ -434,7 +434,7 @@ export async function restoreNoteVersion(noteId: string, historyEntryId: string)
},
})
revalidatePath('/')
revalidatePath('/home')
return parseNote(restored)
}
@@ -603,7 +603,7 @@ export async function createNote(data: {
if (!data.skipRevalidation) {
// Revalidate main page (handles both inbox and notebook views via query params)
revalidatePath('/')
revalidatePath('/home')
}
// Fire-and-forget: run AI operations in background without blocking the response
@@ -690,7 +690,7 @@ export async function createNote(data: {
const merged = [...new Set([...existingNames, ...appliedLabels])]
await syncNoteLabels(noteId, merged, notebookId ?? null, userId)
if (!data.skipRevalidation) {
revalidatePath('/')
revalidatePath('/home')
}
}
}
@@ -853,7 +853,7 @@ export async function updateNote(id: string, data: {
if (!options?.skipRevalidation) {
try { revalidatePath(`/note/${id}`) } catch {}
try { revalidatePath('/') } catch {}
try { revalidatePath('/home') } catch {}
}
if (isStructuralChange) {
@@ -895,7 +895,7 @@ export async function deleteNote(id: string, options?: { skipRevalidation?: bool
})
if (!options?.skipRevalidation) {
revalidatePath('/')
revalidatePath('/home')
}
return { success: true }
} catch (error) {
@@ -915,7 +915,7 @@ export async function trashNote(id: string, options?: { skipRevalidation?: boole
data: { trashedAt: new Date() }
})
if (!options?.skipRevalidation) {
revalidatePath('/')
revalidatePath('/home')
}
return { success: true }
} catch (error) {
@@ -933,7 +933,7 @@ export async function restoreNote(id: string) {
where: { id, userId: session.user.id },
data: { trashedAt: null }
})
revalidatePath('/')
revalidatePath('/home')
revalidatePath('/trash')
return { success: true }
} catch (error) {
@@ -984,7 +984,7 @@ export async function permanentDeleteNote(id: string) {
await syncLabels(session.user.id, [])
revalidatePath('/trash')
revalidatePath('/')
revalidatePath('/home')
return { success: true }
} catch (error) {
console.error('Error permanently deleting note:', error)
@@ -1028,7 +1028,7 @@ export async function emptyTrash() {
await syncLabels(session.user.id, [])
revalidatePath('/trash')
revalidatePath('/')
revalidatePath('/home')
return { success: true }
} catch (error) {
console.error('Error emptying trash:', error)
@@ -1182,7 +1182,7 @@ export async function reorderNotes(draggedId: string, targetId: string) {
prisma.note.update({ where: { id: note.id }, data: { order: index } })
)
await prisma.$transaction(updates)
revalidatePath('/')
revalidatePath('/home')
return { success: true }
} catch (error) {
throw new Error('Failed to reorder notes')
@@ -1198,7 +1198,7 @@ export async function updateFullOrder(ids: string[]) {
prisma.note.update({ where: { id, userId }, data: { order: index } })
)
await prisma.$transaction(updates)
revalidatePath('/')
revalidatePath('/home')
return { success: true }
} catch (error) {
throw new Error('Failed to update order')
@@ -1314,7 +1314,7 @@ export async function cleanupAllOrphans() {
}
}
revalidatePath('/')
revalidatePath('/home')
revalidatePath('/settings')
return {
success: true,
@@ -1487,7 +1487,7 @@ export async function dismissFromRecent(id: string) {
data: { dismissedFromRecent: true }
})
// revalidatePath('/') // Removed to prevent immediate refill of the list
// revalidatePath('/home') // Removed to prevent immediate refill of the list
return { success: true }
} catch (error) {
console.error('Error dismissing note from recent:', error)
@@ -1895,7 +1895,7 @@ export async function respondToShareRequest(shareId: string, action: 'accept' |
});
// Revalidate all relevant cache tags
revalidatePath('/');
revalidatePath('/home');
return { success: true, share: updatedShare };
} catch (error: any) {
@@ -1957,7 +1957,7 @@ export async function removeSharedNoteFromView(shareId: string) {
}
});
revalidatePath('/');
revalidatePath('/home');
return { success: true };
} catch (error: any) {
console.error('Error removing shared note from view:', error);
@@ -2018,7 +2018,7 @@ export async function leaveSharedNote(noteId: string) {
}
});
revalidatePath('/');
revalidatePath('/home');
return { success: true };
} catch (error: any) {
console.error('Error leaving shared note:', error);

View File

@@ -271,7 +271,7 @@ export async function executeNotebookOrganization(plan: OrganizationPlan): Promi
}
}
revalidatePath('/')
revalidatePath('/home')
return { success: true, created, moved }
} catch (err) {
console.error('[organize-notebook] Execute error:', err)

View File

@@ -96,7 +96,7 @@ export async function updateTheme(theme: string) {
where: { id: session.user.id },
data: { theme: normalized },
})
revalidatePath('/')
revalidatePath('/home')
revalidatePath('/settings/profile')
return { success: true }
} catch (error) {
@@ -123,7 +123,7 @@ export async function updateLanguage(language: string) {
// Note: The language will be applied on next page load
// The client component should handle updating localStorage and reloading
revalidatePath('/')
revalidatePath('/home')
revalidatePath('/settings/profile')
return { success: true, language }
} catch (error) {
@@ -168,7 +168,7 @@ export async function updateFontSize(fontSize: string) {
})
}
revalidatePath('/')
revalidatePath('/home')
revalidatePath('/settings/profile')
return { success: true, fontSize }
} catch (error) {
@@ -194,7 +194,7 @@ export async function updateShowRecentNotes(showRecentNotes: boolean) {
},
})
revalidatePath('/')
revalidatePath('/home')
revalidatePath('/settings/profile')
return { success: true, showRecentNotes }
} catch (error) {

View File

@@ -99,7 +99,7 @@ export async function applyTitleSuggestion(
console.error('[HISTORY] Failed to create snapshot after title suggestion:', snapshotError)
}
revalidatePath('/')
revalidatePath('/home')
revalidatePath(`/note/${noteId}`)
} catch (error) {
console.error('Error applying title suggestion:', error)

View File

@@ -2,6 +2,7 @@ import { NextRequest, NextResponse } from 'next/server'
import { auth } from '@/auth'
import { paragraphRefactorService } from '@/lib/ai/services/paragraph-refactor.service'
import { getAISettings } from '@/app/actions/ai-settings'
import { checkEntitlementOrThrow, QuotaExceededError, incrementUsageAsync } from '@/lib/entitlements'
export async function POST(request: NextRequest) {
try {
@@ -52,9 +53,27 @@ export async function POST(request: NextRequest) {
}, { status: 400 })
}
// Check quota
try {
await checkEntitlementOrThrow(session.user.id, 'reformulate')
} catch (err) {
if (err instanceof QuotaExceededError) {
const isTierLocked = err.currentQuota === 0
return NextResponse.json({
error: isTierLocked ? 'feature_locked' : 'quota_exceeded',
errorKey: isTierLocked ? 'ai.featureLocked' : 'ai.quotaExceeded',
upgradeTier: err.upgradeTier,
quotaExceeded: true,
}, { status: 402 })
}
throw err
}
// Use the ParagraphRefactorService
const result = await paragraphRefactorService.refactor(text, mode, format === 'html' ? 'html' : 'markdown', language)
incrementUsageAsync(session.user.id, 'reformulate')
return NextResponse.json({
originalText: result.original,
reformulatedText: result.refactored,

View File

@@ -67,7 +67,7 @@ async function getParentContext(
FROM "NoteEmbedding" e
JOIN "Note" n ON n.id = e."noteId"
WHERE n."userId" = $1 AND n."trashedAt" IS NULL AND n.id NOT IN (${excludeList})
ORDER BY e.embedding <=> $2::vector
ORDER BY e.embedding::vector <=> $2::vector
LIMIT 5`,
hostUserId, vectorStr
) as any[]

View File

@@ -131,7 +131,7 @@ export async function POST(
FROM "NoteEmbedding" e
JOIN "Note" n ON n.id = e."noteId"
WHERE n.id IN (${idList}) AND n."trashedAt" IS NULL
ORDER BY e.embedding <=> $1::vector
ORDER BY e.embedding::vector <=> $1::vector
LIMIT 3`,
vectorStr
) as any[]
@@ -142,7 +142,7 @@ export async function POST(
FROM "NoteEmbedding" e
JOIN "Note" n ON n.id = e."noteId"
WHERE n."userId" = $1 AND n."trashedAt" IS NULL
ORDER BY e.embedding <=> $2::vector
ORDER BY e.embedding::vector <=> $2::vector
LIMIT 3`,
aiUserId, vectorStr
) as any[]

View File

@@ -44,7 +44,7 @@ async function autoContextSearch(
FROM "NoteEmbedding" e
JOIN "Note" n ON n.id = e."noteId"
WHERE n."userId" = $1 AND n."trashedAt" IS NULL
ORDER BY e.embedding <=> $2::vector
ORDER BY e.embedding::vector <=> $2::vector
LIMIT 8`,
userId, vectorStr
) as any[]

View File

@@ -146,7 +146,7 @@ export async function PUT(
})
// Revalidate to refresh UI
revalidatePath('/')
revalidatePath('/home')
return NextResponse.json({
success: true,
@@ -253,7 +253,7 @@ export async function DELETE(
})
// Revalidate to refresh UI
revalidatePath('/')
revalidatePath('/home')
return NextResponse.json({
success: true,

View File

@@ -6,7 +6,7 @@ export async function GET() {
name: "Memento Notes",
short_name: "Memento",
description: "A smart, local-first note taking app with AI capabilities.",
start_url: "/",
start_url: "/home",
display: "standalone",
background_color: "#F2F0E9",
theme_color: "#1C1C1C",

View File

@@ -98,7 +98,7 @@ export async function PATCH(
})
}
try { revalidatePath('/') } catch {}
try { revalidatePath('/home') } catch {}
return NextResponse.json({ success: true })
} catch (error) {
@@ -143,7 +143,7 @@ export async function DELETE(
await prisma.notebook.delete({ where: { id } })
try { revalidatePath('/') } catch {}
try { revalidatePath('/home') } catch {}
return NextResponse.json({
success: true,

View File

@@ -47,7 +47,7 @@ export async function POST(request: NextRequest) {
await prisma.$transaction(updates)
revalidatePath('/')
revalidatePath('/home')
return NextResponse.json({
success: true,

View File

@@ -105,7 +105,7 @@ export async function POST(request: NextRequest) {
}
})
try { revalidatePath('/') } catch {}
try { revalidatePath('/home') } catch {}
return NextResponse.json({
success: true,

View File

@@ -90,7 +90,7 @@ export async function POST(
console.error('[HISTORY] Failed to create snapshot after notebook move:', snapshotError)
}
// No revalidatePath('/') here — the client-side triggerRefresh() in
// No revalidatePath('/home') here — the client-side triggerRefresh() in
// notebooks-context.tsx handles the refresh. Avoiding server-side
// revalidation prevents a double-refresh (server + client).

View File

@@ -50,7 +50,7 @@ export async function POST(req: NextRequest) {
})
// Revalidate paths
revalidatePath('/')
revalidatePath('/home')
revalidatePath('/settings/data')
// Await cleanup in background (don't block response)

View File

@@ -222,7 +222,7 @@ export async function POST(req: NextRequest) {
}
}
revalidatePath('/')
revalidatePath('/home')
revalidatePath('/settings/data')
return NextResponse.json({ success: true, ...stats })

View File

@@ -1,6 +1,6 @@
import { NextResponse } from 'next/server';
import { auth } from '@/auth';
import { getUserQuotas } from '@/lib/entitlements';
import { getUserQuotas, getEffectiveTier } from '@/lib/entitlements';
export async function GET() {
const session = await auth();
@@ -10,8 +10,11 @@ export async function GET() {
}
try {
const quotas = await getUserQuotas(session.user.id);
return NextResponse.json({ quotas });
const [quotas, tier] = await Promise.all([
getUserQuotas(session.user.id),
getEffectiveTier(session.user.id),
]);
return NextResponse.json({ quotas, tier });
} catch (error) {
console.error('[usage/current] Failed to fetch quotas:', error);
return NextResponse.json(

View File

@@ -8,6 +8,10 @@ export async function GET(request: NextRequest) {
return NextResponse.json({ error: 'Unauthorized' }, { status: 401 })
}
if ((session.user as any)?.role !== 'ADMIN') {
return NextResponse.json({ users: [] })
}
const q = request.nextUrl.searchParams.get('q') || ''
if (q.length < 2) {
return NextResponse.json({ users: [] })

View File

@@ -14,7 +14,7 @@ export const authConfig = {
authorized({ auth, request: { nextUrl } }) {
const isLoggedIn = !!auth?.user;
const isAdmin = (auth?.user as any)?.role === 'ADMIN';
const isDashboardPage = nextUrl.pathname === '/' ||
const isDashboardPage = nextUrl.pathname === '/home' ||
nextUrl.pathname.startsWith('/reminders') ||
nextUrl.pathname.startsWith('/archive') ||
nextUrl.pathname.startsWith('/trash') ||
@@ -24,8 +24,14 @@ export const authConfig = {
nextUrl.pathname.startsWith('/chat') ||
nextUrl.pathname.startsWith('/canvas') ||
nextUrl.pathname.startsWith('/notebooks') ||
nextUrl.pathname.startsWith('/note/');
nextUrl.pathname.startsWith('/note/') ||
nextUrl.pathname.startsWith('/brainstorm');
const isAdminPage = nextUrl.pathname.startsWith('/admin');
const isPublicPage = nextUrl.pathname === '/' ||
nextUrl.pathname === '/login' ||
nextUrl.pathname === '/register' ||
nextUrl.pathname === '/forgot-password' ||
nextUrl.pathname.startsWith('/reset-password');
if (isAdminPage) {
return isLoggedIn && isAdmin;
@@ -34,9 +40,12 @@ export const authConfig = {
if (isDashboardPage) {
if (isLoggedIn) return true;
return false;
} else if (isLoggedIn && (nextUrl.pathname === '/login' || nextUrl.pathname === '/register')) {
return Response.redirect(new URL('/', nextUrl));
}
if (isLoggedIn && (nextUrl.pathname === '/login' || nextUrl.pathname === '/register')) {
return Response.redirect(new URL('/home', nextUrl));
}
return true;
},
async jwt({ token, user }) {

View File

@@ -122,7 +122,7 @@ export function AdminSidebar({ className }: { className?: string }) {
</DropdownMenu>
<a
href="/"
href="/home"
className={cn(
'flex min-w-0 flex-1 items-center gap-2 rounded-xl px-2 py-1.5 transition-colors',
'hover:bg-white/40 dark:hover:bg-white/10'
@@ -143,7 +143,7 @@ export function AdminSidebar({ className }: { className?: string }) {
</div>
<a
href="/"
href="/home"
className={cn(
'flex items-center gap-3 rounded-xl px-4 py-2.5 text-[13px] font-medium transition-all',
'text-muted-foreground hover:bg-white/40 hover:text-foreground dark:hover:bg-white/10'

View File

@@ -205,7 +205,7 @@ export function AgentCard({ agent, onEdit, onRefresh, onToggle }: AgentCardProps
>
<div className="flex items-start justify-between">
<div className="flex items-center gap-4">
<div className="p-3 bg-muted rounded-xl group-hover:bg-foreground group-hover:text-background transition-all">
<div className="p-3 bg-muted rounded-xl group-hover:bg-brand-accent group-hover:text-white transition-all">
<Icon className="w-5 h-5" />
</div>
<div className="space-y-1">
@@ -224,7 +224,7 @@ export function AgentCard({ agent, onEdit, onRefresh, onToggle }: AgentCardProps
>
<div className="relative inline-flex items-center cursor-pointer">
<div className={`w-8 h-4 rounded-full transition-colors ${
agent.isEnabled ? 'bg-primary' : 'bg-muted-foreground/30'
agent.isEnabled ? 'bg-brand-accent' : 'bg-muted-foreground/30'
}`}>
<span className={`absolute top-0.5 left-[2px] bg-background border border-muted-foreground/30 rounded-full h-3 w-3 transition-all ${
agent.isEnabled ? 'translate-x-4' : ''
@@ -260,9 +260,9 @@ export function AgentCard({ agent, onEdit, onRefresh, onToggle }: AgentCardProps
<span className="uppercase tracking-tight">{t('agents.status.lastStatus')}</span>
{lastAction ? (
<span className={`flex items-center gap-1 ${
lastAction.status === 'success' ? 'text-primary'
lastAction.status === 'success' ? 'text-brand-accent'
: lastAction.status === 'failure' ? 'text-destructive'
: lastAction.status === 'running' ? 'text-primary'
: lastAction.status === 'running' ? 'text-brand-accent'
: 'text-muted-foreground'
}`}>
{lastAction.status === 'success' && <Activity className="w-2 h-2" />}

View File

@@ -353,7 +353,7 @@ export function AgentDetailView({
<div className="flex items-end justify-between">
<div className="space-y-4">
<div className="flex items-center gap-3">
<div className="p-4 bg-foreground text-background rounded-2xl shadow-xl shadow-foreground/10">
<div className="p-4 bg-brand-accent text-white rounded-2xl shadow-xl shadow-brand-accent/10">
<Icon className="w-8 h-8" />
</div>
<div className="space-y-1">
@@ -369,7 +369,7 @@ export function AgentDetailView({
{isNew ? t('agents.newBadge') : `ID: ${agent?.id?.slice(0, 8)}`}
</span>
{!isNew && agent?.isEnabled && (
<span className="text-[10px] font-bold uppercase tracking-widest px-2 py-1 bg-primary/10 text-primary rounded-md">
<span className="text-[10px] font-bold uppercase tracking-widest px-2 py-1 bg-brand-accent/10 text-brand-accent rounded-md">
{t('agents.actions.toggleOn')}
</span>
)}
@@ -386,7 +386,7 @@ export function AgentDetailView({
{successRate !== null && (
<div className="flex flex-col items-end gap-1">
<span className="opacity-40">Succès</span>
<span className="text-primary">{successRate}%</span>
<span className="text-brand-accent">{successRate}%</span>
</div>
)}
</div>
@@ -751,7 +751,7 @@ export function AgentDetailView({
<div className="space-y-10">
<section className="space-y-6">
<h3 className={sectionTitleCls}>{t('agents.form.frequency')}<FieldHelp tooltip={t('agents.help.tooltips.frequency')} /></h3>
<div className="bg-foreground rounded-3xl p-8 space-y-8 text-background shadow-2xl shadow-foreground/20 relative overflow-hidden">
<div className="bg-ink rounded-3xl p-8 space-y-8 text-paper shadow-2xl shadow-ink/20 relative overflow-hidden">
<div className="absolute top-0 right-0 p-4 opacity-10">
<Clock className="w-24 h-24" />
</div>

View File

@@ -6,9 +6,8 @@ import { DefaultChatTransport } from 'ai'
import type { UIMessage } from 'ai'
import { cn } from '@/lib/utils'
import {
X, Bot, Sparkles, History, Send, Globe, Briefcase, Palette, GraduationCap, Coffee,
Loader2, Layers, Square, Plus, ChevronRight, MessageSquare, FileCode,
Zap, Network, Clock, Scissors, Languages, Layout, ArrowRightLeft, BookOpen,
X, Bot, Sparkles, History, Send, Globe,
Loader2, Square, Plus, MessageSquare, FileCode,
Maximize2, Minimize2
} from 'lucide-react'
import { useLanguage } from '@/lib/i18n'
@@ -28,14 +27,7 @@ function getTextContent(msg: UIMessage): string {
return ''
}
const TONE_IDS = [
{ id: 'professional', icon: Briefcase },
{ id: 'creative', icon: Palette },
{ id: 'academic', icon: GraduationCap },
{ id: 'casual', icon: Coffee },
] as const
type AITab = 'discussion' | 'actions' | 'explore' | 'resources'
type AITab = 'discussion' | 'history'
export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: boolean } = {}) {
const { t, language } = useLanguage()
@@ -45,7 +37,6 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
const [isOpen, setIsOpen] = useState(false)
const [isExpanded, setIsExpanded] = useState(false)
const [aiTab, setAiTab] = useState<AITab>('discussion')
const [selectedTone, setSelectedTone] = useState('professional')
const [webSearch, setWebSearch] = useState(false)
const [chatScope, setChatScope] = useState<'all' | string>('all')
const [input, setInput] = useState('')
@@ -55,9 +46,6 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
const [history, setHistory] = useState<any[]>([])
const [historyLoading, setHistoryLoading] = useState(false)
const [insights, setInsights] = useState<string>('')
const [insightsLoading, setInsightsLoading] = useState(false)
const messagesEndRef = useRef<HTMLDivElement>(null)
const transport = useRef(new DefaultChatTransport({ api: '/api/chat' })).current
@@ -65,6 +53,23 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
transport,
onError: (error) => {
console.error('Chat error:', error)
try {
const parsed = JSON.parse((error as Error).message || '{}')
if (parsed.error === 'QUOTA_EXCEEDED') {
const isBasic = (parsed.currentTier || 'BASIC') === 'BASIC'
toast.error(
language === 'fr'
? isBasic
? 'Le chat IA est réservé au plan PRO et supérieur.'
: `Limite mensuelle atteinte pour le plan ${parsed.currentTier}. Elle se réinitialise le mois prochain.`
: isBasic
? 'AI Chat is available from the PRO plan onwards.'
: `Monthly quota reached for ${parsed.currentTier} plan. It will reset next month.`,
{ duration: 8000 }
)
return
}
} catch {}
toast.error(t('chat.assistantError') || 'Chat error')
}
})
@@ -91,7 +96,6 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
{ text },
{
body: {
tone: selectedTone,
chatScope,
notebookId: chatScope !== 'all' ? chatScope : undefined,
webSearch: webSearch && webSearchAvailable,
@@ -115,24 +119,6 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
setHistoryLoading(false)
}
const fetchInsights = async () => {
setInsightsLoading(true)
try {
const res = await fetch('/api/chat/insights')
if (res.ok) {
const data = await res.json()
setInsights(data.insight)
}
} catch (e) { console.error(e) }
setInsightsLoading(false)
}
useEffect(() => {
if (aiTab === 'discussion') {
// history is loaded on demand via insights tab
}
}, [aiTab])
useEffect(() => {
if (messagesEndRef.current) {
messagesEndRef.current.scrollIntoView({ behavior: 'smooth' })
@@ -203,6 +189,7 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
<button
onClick={() => setIsOpen(false)}
className="p-1.5 hover:bg-slate-100 dark:hover:bg-white/10 rounded-lg transition-colors text-concrete"
title={t('general.close') || 'Fermer'}
>
<X size={18} />
</button>
@@ -215,22 +202,28 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
{/* Tabs */}
<div className="flex border-b border-border px-2 shrink-0">
{(['discussion', 'actions', 'explore', 'resources'] as AITab[]).map((tab) => {
{(['discussion', 'history'] as AITab[]).map((tab) => {
const labels: Record<AITab, string> = {
discussion: t('ai.chatTab') || 'Discussion',
actions: t('ai.actionsTab') || 'Actions',
explore: t('ai.exploreTab') || 'Explorer',
resources: t('ai.resourcesTab') || 'Ressources',
history: t('ai.historyTab') || 'Historique',
}
const icons: Record<AITab, React.ReactNode> = {
discussion: <MessageSquare size={12} />,
history: <History size={12} />,
}
return (
<button
key={tab}
onClick={() => setAiTab(tab)}
onClick={() => {
setAiTab(tab)
if (tab === 'history') fetchHistory()
}}
className={cn(
"flex-1 py-3 text-[10px] uppercase tracking-[0.2em] font-bold transition-all relative",
"flex-1 py-3 text-[10px] uppercase tracking-[0.2em] font-bold transition-all relative flex items-center justify-center gap-1.5",
aiTab === tab ? 'text-brand-accent' : 'text-concrete hover:text-ink/60'
)}
>
{icons[tab]}
{labels[tab]}
{aiTab === tab && (
<motion.div
@@ -248,38 +241,15 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
<AnimatePresence mode="wait">
{aiTab === 'discussion' && (
<motion.div key="discussion" initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -10 }} className="space-y-6">
{/* Context selector */}
<div className="space-y-3">
<div className="flex items-center justify-between">
<label className="text-[10px] uppercase tracking-[0.2em] font-bold text-concrete">{t('ai.writingTone')}</label>
<div className="flex items-center gap-1">
{TONE_IDS.map((tone) => {
const Icon = tone.icon
return (
<button
key={tone.id}
onClick={() => setSelectedTone(tone.id)}
title={t(`ai.tones.${tone.id}`)}
className={cn(
'w-8 h-8 rounded-lg flex items-center justify-center text-[9px] font-bold transition-all border',
selectedTone === tone.id
? 'bg-brand-accent text-white border-brand-accent shadow-sm'
: 'bg-white/50 dark:bg-white/5 border-border/40 text-concrete hover:border-brand-accent/40'
)}
>
<Icon className="h-3.5 w-3.5" />
</button>
)
})}
</div>
</div>
{/* Scope selector */}
<div className="space-y-2">
<button
onClick={() => setChatScope('all')}
className={cn(
'w-full p-2.5 border rounded-xl text-[11px] flex items-center justify-between transition-all',
chatScope === 'all' ? 'bg-brand-accent/5 border-brand-accent/30' : 'bg-white/50 dark:bg-white/5 border-border/40 hover:border-ink/20'
)}
title={t('ai.allMyNotes') || 'Toutes mes notes'}
>
<div className="flex items-center gap-2.5">
<FileCode size={14} className="text-brand-accent/60" />
@@ -324,14 +294,14 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
<div key={msg.id} className={cn('flex gap-3', msg.role === 'user' && 'flex-row-reverse')}>
<div className={cn(
'w-8 h-8 rounded-xl flex items-center justify-center flex-shrink-0',
msg.role === 'user' ? 'bg-ink text-paper' : 'bg-brand-accent/10 text-brand-accent',
msg.role === 'user' ? 'bg-brand-accent text-white' : 'bg-brand-accent/10 text-brand-accent',
)}>
{msg.role === 'user' ? 'U' : <Bot className="h-4 w-4" />}
</div>
<div className={cn(
'max-w-[85%] p-3.5 rounded-2xl text-sm leading-relaxed',
msg.role === 'user'
? 'bg-ink text-paper rounded-tr-sm'
? 'bg-brand-accent text-white rounded-tr-sm'
: 'bg-white/60 dark:bg-white/5 border border-border rounded-tl-sm text-ink',
)}>
{msg.role === 'assistant' ? <MarkdownContent content={text} /> : <p>{text}</p>}
@@ -354,187 +324,36 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
</motion.div>
)}
{aiTab === 'actions' && (
<motion.div key="actions" initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -10 }} className="space-y-8">
<div className="flex items-center gap-2 mb-2">
<div className="h-px flex-1 bg-border/40" />
<h4 className="text-[10px] uppercase tracking-[0.25em] font-bold text-concrete whitespace-nowrap">Transformations</h4>
<div className="h-px flex-1 bg-border/40" />
</div>
<div className="grid grid-cols-2 gap-2">
{[
{ icon: <Sparkles size={14} />, label: t('ai.actionClarify') || 'Clarifier' },
{ icon: <Scissors size={14} />, label: t('ai.actionShorten') || 'Raccourcir' },
{ icon: <Zap size={14} />, label: t('ai.actionImprove') || 'Améliorer' },
{ icon: <Languages size={14} />, label: t('ai.actionTranslate') || 'Traduire' },
].map((action, i) => (
<button key={i} className="flex flex-col items-center gap-3 p-4 bg-white/50 dark:bg-white/5 border border-border rounded-xl transition-all group hover:border-ink/20">
<div className="p-2 rounded-lg bg-slate-50 dark:bg-white/10 transition-colors group-hover:bg-brand-accent group-hover:text-white shadow-sm text-concrete">
{action.icon}
{aiTab === 'history' && (
<motion.div key="history" initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -10 }} className="space-y-3">
{historyLoading ? (
<div className="flex justify-center py-12">
<Loader2 className="h-6 w-6 animate-spin text-concrete" />
</div>
) : history.length === 0 ? (
<div className="flex flex-col items-center justify-center py-12 text-concrete/30">
<History size={24} />
<p className="text-[11px] mt-3 italic">{t('ai.noHistory') || 'Aucun historique'}</p>
</div>
) : (
history.map((conv: any) => (
<button
key={conv.id}
onClick={() => { setConversationId(conv.id); setMessages(conv.messages || []); setAiTab('discussion') }}
className="w-full text-left p-4 bg-white/50 dark:bg-white/5 border border-border rounded-xl hover:border-brand-accent/30 transition-all group"
>
<div className="flex items-center gap-3">
<div className="p-2 rounded-lg bg-brand-accent/10 text-brand-accent group-hover:bg-brand-accent group-hover:text-white transition-colors">
<MessageSquare size={14} />
</div>
<div className="flex-1 min-w-0">
<p className="text-sm font-medium text-ink truncate">{conv.title || conv.id}</p>
<p className="text-[10px] text-concrete mt-0.5">{new Date(conv.createdAt).toLocaleDateString()}</p>
</div>
</div>
<span className="text-[10px] font-bold text-ink/80 uppercase tracking-widest">{action.label}</span>
</button>
))}
<button className="col-span-2 flex items-center justify-center gap-3 py-3 px-4 bg-white/50 dark:bg-white/5 border border-border rounded-xl text-[10px] font-bold text-ink/80 hover:bg-white dark:hover:bg-white/10 transition-colors hover:border-ink/20 uppercase tracking-widest">
<FileCode size={14} className="text-concrete" />
{t('ai.actionMarkdown') || 'Convertir en Markdown'}
</button>
</div>
<div className="space-y-4">
<div className="flex items-center gap-2 mb-2">
<div className="h-px flex-1 bg-border/40" />
<h4 className="text-[10px] uppercase tracking-[0.25em] font-bold text-concrete whitespace-nowrap">Generation Tools</h4>
<div className="h-px flex-1 bg-border/40" />
</div>
<div className="group relative p-6 rounded-2xl bg-white border border-border hover:border-brand-accent/30 transition-all duration-500 overflow-hidden">
<div className="absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity">
<Layout size={80} className="text-brand-accent" />
</div>
<div className="relative space-y-5">
<div className="flex items-center gap-3">
<div className="p-2 bg-slate-50 rounded-lg text-brand-accent"><Layout size={18} /></div>
<div className="space-y-0.5">
<h5 className="text-sm font-bold text-ink leading-none">{t('ai.slides') || 'Présentation'}</h5>
<p className="text-[10px] text-concrete uppercase tracking-tight">{t('ai.slidesDesc') || 'Convertir en slides interactives'}</p>
</div>
</div>
<button className="w-full py-3.5 bg-brand-accent text-white rounded-xl text-[10px] font-bold flex items-center justify-center gap-2 hover:opacity-90 transition-all shadow-lg shadow-brand-accent/20 uppercase tracking-[0.2em]">
{t('ai.generate') || 'Générer'} <ArrowRightLeft size={14} className="opacity-60" />
</button>
</div>
</div>
<div className="group relative p-6 rounded-2xl bg-white border border-border hover:border-emerald-500/30 transition-all duration-500 overflow-hidden">
<div className="absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity">
<BookOpen size={80} className="text-emerald-500" />
</div>
<div className="relative space-y-5">
<div className="flex items-center gap-3">
<div className="p-2 bg-slate-50 rounded-lg text-emerald-500"><BookOpen size={18} /></div>
<div className="space-y-0.5">
<h5 className="text-sm font-bold text-ink leading-none">{t('ai.diagram') || 'Diagramme'}</h5>
<p className="text-[10px] text-concrete uppercase tracking-tight">{t('ai.diagramDesc') || 'Visualisation de structure'}</p>
</div>
</div>
<button className="w-full py-3.5 bg-emerald-600 text-white rounded-xl text-[10px] font-bold flex items-center justify-center gap-2 hover:opacity-90 transition-all shadow-lg shadow-emerald-600/20 uppercase tracking-[0.2em]">
{t('ai.trace') || 'Tracer'} <ArrowRightLeft size={14} className="opacity-60" />
</button>
</div>
</div>
</div>
<div className="flex flex-col items-center gap-2 opacity-20 py-4">
<History size={16} />
<span className="text-[10px] font-bold uppercase tracking-widest whitespace-nowrap">Auto-Save Enabled</span>
</div>
</motion.div>
)}
{aiTab === 'explore' && (
<motion.div key="explore" initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -10 }} className="space-y-6">
<div className="flex items-center gap-2 mb-2">
<div className="h-px flex-1 bg-border/40" />
<h4 className="text-[10px] uppercase tracking-[0.25em] font-bold text-concrete whitespace-nowrap">Intelligence Modules</h4>
<div className="h-px flex-1 bg-border/40" />
</div>
<div className="space-y-3">
<button className="w-full group relative p-5 rounded-2xl bg-white border border-border hover:border-brand-accent/30 transition-all text-left overflow-hidden">
<div className="absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity">
<Zap size={60} className="text-brand-accent" />
</div>
<div className="relative flex items-center gap-4">
<div className="p-3 bg-brand-accent/10 rounded-xl text-brand-accent group-hover:bg-brand-accent group-hover:text-white transition-colors">
<Zap size={20} />
</div>
<div>
<h5 className="font-bold text-ink text-sm">{t('ai.brainstormWave') || 'Brainstorm Wave'}</h5>
<p className="text-[10px] text-concrete uppercase tracking-tight">{t('ai.brainstormWaveDesc') || 'Unfold dimensions of thought'}</p>
</div>
</div>
</button>
<button className="w-full group relative p-5 rounded-2xl bg-white border border-border hover:border-indigo-500/30 transition-all text-left overflow-hidden">
<div className="absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity">
<Network size={60} className="text-indigo-500" />
</div>
<div className="relative flex items-center gap-4">
<div className="p-3 bg-indigo-500/10 rounded-xl text-indigo-500 group-hover:bg-indigo-500 group-hover:text-white transition-colors">
<Network size={20} />
</div>
<div>
<h5 className="font-bold text-ink text-sm">{t('ai.semanticNetwork') || 'Réseau Sémantique'}</h5>
<p className="text-[10px] text-concrete uppercase tracking-tight">{t('ai.semanticNetworkDesc') || 'Detect clusters and bridges'}</p>
</div>
</div>
</button>
<button className="w-full group relative p-5 rounded-2xl bg-white border border-border hover:border-rose-500/30 transition-all text-left overflow-hidden">
<div className="absolute top-0 right-0 p-4 opacity-5 group-hover:opacity-10 transition-opacity">
<Clock size={60} className="text-rose-500" />
</div>
<div className="relative flex items-center gap-4">
<div className="p-3 bg-rose-500/10 rounded-xl text-rose-500 group-hover:bg-rose-500 group-hover:text-white transition-colors">
<Clock size={20} />
</div>
<div>
<h5 className="font-bold text-ink text-sm">{t('ai.temporalForecast') || 'Prévision Temporelle'}</h5>
<p className="text-[10px] text-concrete uppercase tracking-tight">{t('ai.temporalForecastDesc') || 'Predict relevance recurrence'}</p>
</div>
</div>
</button>
</div>
<div className="p-6 rounded-2xl bg-slate-50 dark:bg-white/5 border border-dashed border-border">
<p className="text-[10px] text-concrete leading-relaxed font-medium italic text-center">
{t('ai.modulesHint') || 'Ces modules utilisent les embeddings pour analyser vos pensées.'}
</p>
</div>
</motion.div>
)}
{aiTab === 'resources' && (
<motion.div key="resources" initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} exit={{ opacity: 0, y: -10 }} className="space-y-6">
<div className="space-y-2">
<label className="text-[10px] uppercase tracking-[0.2em] font-bold text-concrete">{t('ai.resourceUrl') || 'URL (Optionnel)'}</label>
<div className="relative">
<input type="text" placeholder="https://..." className="w-full bg-white/50 dark:bg-white/5 border border-border rounded-xl pl-4 pr-10 py-3 text-xs outline-none focus:border-brand-accent transition-colors text-ink" />
<Globe size={14} className="absolute right-3 top-1/2 -translate-y-1/2 text-concrete/40" />
</div>
</div>
<div className="space-y-2">
<label className="text-[10px] uppercase tracking-[0.2em] font-bold text-concrete">{t('ai.resourceText') || 'Texte de la ressource'}</label>
<textarea
rows={8}
placeholder={t('ai.resourcePlaceholder') || 'Collez votre texte ici...'}
className="w-full bg-white/50 dark:bg-white/5 border border-border rounded-xl p-4 text-xs outline-none focus:border-brand-accent transition-colors resize-none leading-relaxed text-ink"
/>
</div>
<div className="space-y-3">
<label className="text-[10px] uppercase tracking-[0.2em] font-bold text-concrete">{t('ai.integrationMode') || "Mode d'intégration"}</label>
<div className="grid grid-cols-3 gap-2">
{[
{ id: 'replace', label: t('ai.modeReplace') || 'Remplacer', sub: 'Direct' },
{ id: 'append', label: t('ai.modeAppend') || 'Compléter', sub: 'Ajoute' },
{ id: 'merge', label: t('ai.modeMerge') || 'Fusionner', sub: 'Intègre' },
].map((mode) => (
<button key={mode.id} className="flex flex-col items-center justify-center p-3 rounded-xl border transition-all text-center bg-white border-border hover:bg-slate-50 dark:hover:bg-white/5">
<span className="text-[10px] font-bold text-ink">{mode.label}</span>
<span className="text-[8px] text-concrete opacity-60 leading-tight mt-1 font-medium">{mode.sub}</span>
</button>
))}
</div>
</div>
<button className="w-full py-4 bg-brand-accent text-white rounded-xl text-[11px] font-bold uppercase tracking-[0.2em] flex items-center justify-center gap-3 hover:opacity-90 transition-opacity shadow-lg shadow-brand-accent/20">
<Sparkles size={18} />
{t('ai.generatePreview') || "Générer l'aperçu"}
</button>
))
)}
</motion.div>
)}
</AnimatePresence>
@@ -561,6 +380,15 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
}}
disabled={isLoading}
/>
<div className="absolute left-6 bottom-4 flex gap-3 text-concrete/40">
<button
onClick={() => webSearchAvailable && setWebSearch(!webSearch)}
className={cn("hover:text-brand-accent transition-colors", webSearch && "text-brand-accent")}
title={webSearch ? (t('ai.webSearchEnabled') || 'Recherche web activée') : (t('ai.webSearchDisabled') || 'Activer la recherche web')}
>
<Globe size={14} />
</button>
</div>
<div className="absolute right-4 bottom-4 flex flex-col gap-2">
{isLoading ? (
<button onClick={() => stop()} className="p-2.5 bg-rose-500 text-white rounded-xl transition-all hover:scale-110 active:scale-95 shadow-lg shadow-rose-500/20">
@@ -572,18 +400,6 @@ export function AIChat({ showFloatingTrigger = true }: { showFloatingTrigger?: b
</button>
)}
</div>
<div className="absolute left-6 bottom-4 flex gap-3 text-concrete/40">
<button
onClick={() => webSearchAvailable && setWebSearch(!webSearch)}
className={cn("hover:text-brand-accent transition-colors", webSearch && "text-brand-accent")}
>
<Globe size={14} />
</button>
<button className="hover:text-brand-accent transition-colors"><Network size={14} /></button>
</div>
</div>
<div className="flex justify-center mt-4">
<p className="text-[9px] text-concrete/40 uppercase tracking-[0.3em] font-bold">Shift+Enter for new line</p>
</div>
</motion.div>
)}

View File

@@ -1,7 +1,7 @@
'use client'
import { useState, useCallback } from 'react'
import { PageEntry } from '@/components/page-entry'
import dynamic from 'next/dynamic'
import type { Note } from '@/lib/types'
import { NotesEditorialView } from '@/components/notes-editorial-view'
@@ -41,11 +41,9 @@ export function ArchiveClient({ notes }: ArchiveClientProps) {
}
return (
<PageEntry>
<NotesEditorialView
notes={notes}
onOpen={handleOpen}
/>
</PageEntry>
)
}

View File

@@ -213,7 +213,7 @@ export function BrainstormPage() {
setConvertToast({ noteTitle: result.title || idea.title, noteId: result.id })
setTimeout(() => {
setConvertToast(null)
router.push(`/?openNote=${result.id}`)
router.push(`/home?openNote=${result.id}`)
}, 2000)
}
} catch {}
@@ -228,7 +228,7 @@ export function BrainstormPage() {
setExportToast({ noteTitle: result.title || t('brainstorm.exportDefaultNoteTitle'), notebookName })
setTimeout(() => {
setExportToast(null)
router.push(`/?openNote=${result.id}`)
router.push(`/home?openNote=${result.id}`)
}, 2000)
return
}
@@ -634,7 +634,7 @@ export function BrainstormPage() {
</div>
{ref.noteId && (
<button
onClick={() => router.push(`/?openNote=${ref.noteId}`)}
onClick={() => router.push(`/home?openNote=${ref.noteId}`)}
className="shrink-0 px-2 py-1 text-[9px] font-bold uppercase tracking-wider rounded-lg bg-foreground/5 hover:bg-foreground/10 text-muted-foreground hover:text-foreground transition-all"
>
{t('brainstorm.viewNote') || 'View'}

View File

@@ -137,8 +137,8 @@ export function BrainstormShareDialog({
<DialogContent className="sm:max-w-md bg-white dark:bg-[#1A1A1A] border-border rounded-2xl">
<DialogHeader>
<DialogTitle className="flex items-center gap-2 text-foreground">
<div className="w-7 h-7 rounded-lg bg-orange-500/10 flex items-center justify-center">
<UserPlus size={14} className="text-orange-500" />
<div className="w-7 h-7 rounded-lg bg-brand-accent/10 flex items-center justify-center">
<UserPlus size={14} className="text-brand-accent" />
</div>
<span className="font-serif">{t('brainstorm.shareDialogTitle')}</span>
</DialogTitle>
@@ -159,7 +159,7 @@ export function BrainstormShareDialog({
onFocus={() => results.length > 0 && setShowDropdown(true)}
onBlur={() => setTimeout(() => setShowDropdown(false), 150)}
placeholder={t('brainstorm.shareNameOrEmailPlaceholder')}
className="w-full px-4 py-3 text-sm border border-border rounded-xl bg-transparent focus:outline-none focus:ring-2 focus:ring-orange-500/20 focus:border-orange-500/40 transition-all"
className="w-full px-4 py-3 text-sm border border-border rounded-xl bg-transparent focus:outline-none focus:ring-2 focus:ring-brand-accent/20 focus:border-brand-accent/40 transition-all"
autoFocus
/>
@@ -173,9 +173,9 @@ export function BrainstormShareDialog({
e.preventDefault()
selectUser(user)
}}
className="w-full px-4 py-2.5 flex items-center gap-3 hover:bg-orange-500/5 transition-colors text-left"
className="w-full px-4 py-2.5 flex items-center gap-3 hover:bg-brand-accent/5 transition-colors text-left"
>
<div className="w-8 h-8 rounded-full bg-orange-500/10 flex items-center justify-center text-xs font-bold text-orange-600 shrink-0">
<div className="w-8 h-8 rounded-full bg-brand-accent/10 flex items-center justify-center text-xs font-bold text-brand-accent shrink-0">
{(user.name || user.email).charAt(0).toUpperCase()}
</div>
<div className="min-w-0 flex-1">
@@ -214,7 +214,7 @@ export function BrainstormShareDialog({
<button
type="submit"
disabled={!query.trim() || isPending}
className="w-full py-3 bg-orange-500 hover:bg-orange-600 text-white text-[10px] font-bold uppercase tracking-[0.15em] rounded-xl disabled:opacity-50 transition-all flex items-center justify-center gap-1.5"
className="w-full py-3 bg-brand-accent hover:bg-brand-accent/90 text-white text-[10px] font-bold uppercase tracking-[0.15em] rounded-xl disabled:opacity-50 transition-all flex items-center justify-center gap-1.5"
>
<UserPlus size={12} />
{isPending ? t('brainstorm.shareSubmitting') : t('brainstorm.shareSubmit')}

View File

@@ -1,6 +1,6 @@
'use client'
import React, { useEffect, useState, useRef } from 'react'
import React, { useEffect, useRef } from 'react'
import { motion, AnimatePresence } from 'motion/react'
interface GhostCursorProps {
@@ -10,114 +10,132 @@ interface GhostCursorProps {
}
export function GhostCursor({ isActive, containerRef, targetId }: GhostCursorProps) {
const [position, setPosition] = useState({ x: 0, y: 0 })
const [visible, setVisible] = useState(false)
const intervalRef = useRef<NodeJS.Timeout | null>(null)
const positionRef = useRef({ x: 0, y: 0 })
const visibleRef = useRef(false)
const elRef = useRef<HTMLDivElement>(null)
const rafRef = useRef<number | null>(null)
const targetRef = useRef({ x: 0, y: 0 })
const initializedRef = useRef(false)
const targetIdRef = useRef(targetId)
targetIdRef.current = targetId
const isActiveRef = useRef(isActive)
isActiveRef.current = isActive
useEffect(() => {
if (!isActive) {
setVisible(false)
if (intervalRef.current) clearInterval(intervalRef.current)
visibleRef.current = false
initializedRef.current = false
if (elRef.current) elRef.current.style.opacity = '0'
if (rafRef.current) cancelAnimationFrame(rafRef.current)
return
}
const container = containerRef.current
if (!container) return
setVisible(true)
// Initialisation sécurisée
const initialRect = container.getBoundingClientRect()
const initialCx = initialRect.width > 0 ? initialRect.width / 2 : window.innerWidth / 2
const initialCy = initialRect.height > 0 ? initialRect.height / 2 : window.innerHeight / 2
setPosition({
x: initialCx + (Math.random() - 0.5) * 200,
y: initialCy + (Math.random() - 0.5) * 200,
})
let angle = Math.random() * Math.PI * 2
let targetX = initialCx + Math.cos(angle) * 250
let targetY = initialCy + Math.sin(angle) * 250
intervalRef.current = setInterval(() => {
// Recalculer les dimensions à chaque tick pour s'adapter aux redimensionnements
const currentContainer = containerRef.current
if (!currentContainer) return
const init = () => {
const container = containerRef.current
if (!container) { rafRef.current = requestAnimationFrame(init); return }
const rect = container.getBoundingClientRect()
if (rect.width === 0 || rect.height === 0) { rafRef.current = requestAnimationFrame(init); return }
const cx = rect.width / 2
const cy = rect.height / 2
targetRef.current = { x: cx + (Math.random() - 0.5) * 200, y: cy + (Math.random() - 0.5) * 200 }
positionRef.current = { ...targetRef.current }
initializedRef.current = true
visibleRef.current = true
if (elRef.current) {
elRef.current.style.opacity = '1'
elRef.current.style.transform = `translate(${positionRef.current.x}px, ${positionRef.current.y}px)`
}
}
rafRef.current = requestAnimationFrame(init)
const tick = () => {
if (!isActiveRef.current || !initializedRef.current) {
rafRef.current = requestAnimationFrame(tick)
return
}
const container = containerRef.current
if (!container) { rafRef.current = requestAnimationFrame(tick); return }
const containerRect = container.getBoundingClientRect()
if (containerRect.width === 0 || containerRect.height === 0) { rafRef.current = requestAnimationFrame(tick); return }
const containerRect = currentContainer.getBoundingClientRect()
const cx = containerRect.width / 2
const cy = containerRect.height / 2
let tx = targetRef.current.x
let ty = targetRef.current.y
let currentTargetX = targetX;
let currentTargetY = targetY;
if (targetId) {
const nodeElement = document.querySelector(`[data-id="${targetId}"]`);
const currentTargetId = targetIdRef.current
if (currentTargetId) {
const nodeElement = container.querySelector(`[data-id="${currentTargetId}"]`) as HTMLElement | null
if (nodeElement) {
const nodeRect = nodeElement.getBoundingClientRect();
currentTargetX = nodeRect.left - containerRect.left + nodeRect.width / 2;
currentTargetY = nodeRect.top - containerRect.top + nodeRect.height / 2;
const nodeRect = nodeElement.getBoundingClientRect()
tx = nodeRect.left - containerRect.left + nodeRect.width / 2
ty = nodeRect.top - containerRect.top + nodeRect.height / 2
}
}
setPosition(prev => {
const dx = currentTargetX - prev.x
const dy = currentTargetY - prev.y
const dist = Math.sqrt(dx * dx + dy * dy)
const prev = positionRef.current
const dx = tx - prev.x
const dy = ty - prev.y
const dist = Math.sqrt(dx * dx + dy * dy)
if (!targetId && dist < 20) {
angle = Math.random() * Math.PI * 2
const radius = 150 + Math.random() * 200
targetX = cx + Math.cos(angle) * radius
targetY = cy + Math.sin(angle) * radius
}
if (!currentTargetId && dist < 20) {
angle = Math.random() * Math.PI * 2
const radius = 150 + Math.random() * 200
tx = cx + Math.cos(angle) * radius
ty = cy + Math.sin(angle) * radius
targetRef.current = { x: tx, y: ty }
}
const speed = targetId ? 0.15 : 0.06;
let newX = prev.x + dx * speed;
let newY = prev.y + dy * speed;
// Protection Anti-NaN qui bloquait le curseur en haut à gauche
if (isNaN(newX)) newX = cx;
if (isNaN(newY)) newY = cy;
const speed = currentTargetId ? 0.12 : 0.04
let newX = prev.x + (tx - prev.x) * speed
let newY = prev.y + (ty - prev.y) * speed
if (isNaN(newX)) newX = cx
if (isNaN(newY)) newY = cy
return {
x: newX,
y: newY,
}
})
}, 50)
positionRef.current = { x: newX, y: newY }
if (elRef.current) {
elRef.current.style.transform = `translate(${newX}px, ${newY}px)`
}
rafRef.current = requestAnimationFrame(tick)
}
rafRef.current = requestAnimationFrame(tick)
return () => {
if (intervalRef.current) clearInterval(intervalRef.current)
if (rafRef.current) cancelAnimationFrame(rafRef.current)
}
}, [isActive, containerRef, targetId])
}, [isActive, containerRef])
return (
<AnimatePresence>
{visible && (
<motion.div
initial={{ opacity: 0, scale: 0.5 }}
animate={{ opacity: 1, scale: 1 }}
exit={{ opacity: 0, scale: 0.5 }}
className="absolute pointer-events-none z-50"
style={{ transform: `translate(${position.x}px, ${position.y}px)` }}
>
<div className="relative">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M0 0L16 6L8 8L6 16L0 0Z" fill="#a78bfa" />
</svg>
<div className="absolute -top-1 -right-1 w-3 h-3">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-violet-400 opacity-50" />
<span className="relative inline-flex rounded-full h-3 w-3 bg-violet-500" />
</div>
<div className="mt-3 ml-3 px-2 py-0.5 rounded-full text-[10px] font-bold text-white whitespace-nowrap shadow-lg bg-gradient-to-r from-violet-500 to-purple-600">
AI
</div>
</div>
</motion.div>
)}
</AnimatePresence>
<div
ref={elRef}
className="absolute pointer-events-none z-50"
style={{
left: 0,
top: 0,
opacity: 0,
transition: 'opacity 0.3s ease',
}}
>
<div className="relative">
<svg width="16" height="16" viewBox="0 0 16 16" fill="none">
<path d="M0 0L16 6L8 8L6 16L0 0Z" fill="#a78bfa" />
</svg>
<div className="absolute -top-1 -right-1 w-3 h-3">
<span className="absolute inline-flex h-full w-full animate-ping rounded-full bg-violet-400 opacity-50" />
<span className="relative inline-flex rounded-full h-3 w-3 bg-violet-500" />
</div>
<div className="mt-3 ml-3 px-2 py-0.5 rounded-full text-[10px] font-bold text-white whitespace-nowrap shadow-lg bg-gradient-to-r from-violet-500 to-purple-600">
AI
</div>
</div>
</div>
)
}

View File

@@ -564,16 +564,16 @@ export function ContextualAIChat({
<div className="p-6 border-b border-border/60 space-y-1.5 bg-white/50 dark:bg-black/20 backdrop-blur-md shrink-0">
<div className="flex items-center justify-between">
<div>
<div className="min-w-0 flex-1">
<h3 className="flex items-center gap-2 font-serif text-xl font-medium text-ink">
<Sparkles size={18} className="text-brand-accent" />
<Sparkles size={18} className="text-brand-accent shrink-0" />
{t('ai.assistantTitle') || 'IA Assistant'}
</h3>
<p className="text-[11px] text-concrete uppercase tracking-wider font-medium opacity-60 truncate">
"{noteTitle || t('ai.currentNote')}"
</p>
</div>
<div className="flex items-center gap-1 shrink-0">
<div className="flex items-center gap-1 shrink-0 ml-2">
<button
onClick={() => setExpanded(e => !e)}
className="p-1.5 hover:bg-slate-100 dark:hover:bg-white/10 rounded-lg transition-colors text-concrete"
@@ -584,6 +584,7 @@ export function ContextualAIChat({
<button
onClick={onClose}
className="p-1.5 hover:bg-slate-100 dark:hover:bg-white/10 rounded-lg transition-colors text-concrete"
title={t('general.close') || 'Fermer'}
>
<X size={18} />
</button>

View File

@@ -40,7 +40,10 @@ export function HierarchicalNotebookSelector({
const getDropdownStyle = useCallback((): React.CSSProperties => {
if (!triggerRef.current) return { position: 'fixed', top: 0, left: 0, width: 280, zIndex: 9999 }
const rect = triggerRef.current.getBoundingClientRect()
if (dropUp) {
const dropdownHeight = 350
const viewportHeight = window.innerHeight
const wouldOverflowBottom = rect.bottom + 8 + dropdownHeight > viewportHeight
if (dropUp || wouldOverflowBottom) {
return {
position: 'fixed',
bottom: window.innerHeight - rect.top + 8,

View File

@@ -23,7 +23,7 @@ import { NoteHistoryModal } from '@/components/note-history-modal'
import { CreateNotebookDialog } from '@/components/create-notebook-dialog'
import { toast } from 'sonner'
import { AnimatePresence, motion } from 'motion/react'
import { PageEntry } from '@/components/page-entry'
type SortOrder = 'newest' | 'oldest' | 'alpha' | 'manual'
@@ -111,7 +111,7 @@ export function HomeClient({ initialNotes, initialSettings }: HomeClientProps) {
setEditingNote(null)
const params = new URLSearchParams(searchParams.toString())
params.delete('forceList')
const newUrl = params.toString() ? `/?${params.toString()}` : '/'
const newUrl = params.toString() ? `/home?${params.toString()}` : '/home'
router.replace(newUrl, { scroll: false })
}
}, [searchParams, router])
@@ -441,7 +441,7 @@ export function HomeClient({ initialNotes, initialSettings }: HomeClientProps) {
const params = new URLSearchParams(searchParams.toString())
params.delete('openNote')
const qs = params.toString()
router.replace(qs ? `/?${qs}` : '/', { scroll: false })
router.replace(qs ? `/home?${qs}` : '/home', { scroll: false })
// Invalidate notes cache and trigger refresh
refreshNotes(searchParams.get('notebook') || null)
}, [refreshNotes, router, searchParams])
@@ -457,7 +457,6 @@ export function HomeClient({ initialNotes, initialSettings }: HomeClientProps) {
}, [refreshNotes])
return (
<PageEntry>
<div
className={cn(
'flex w-full min-h-0 flex-1 flex-col gap-3 py-1'
@@ -543,7 +542,7 @@ export function HomeClient({ initialNotes, initialSettings }: HomeClientProps) {
} else {
params.delete('search')
}
router.push(`/?${params.toString()}`)
router.push(`/home?${params.toString()}`)
}}
onBlur={() => {
if (!inlineSearchQuery) {
@@ -556,7 +555,7 @@ export function HomeClient({ initialNotes, initialSettings }: HomeClientProps) {
setInlineSearchQuery('')
const params = new URLSearchParams(searchParams.toString())
params.delete('search')
router.push(`/?${params.toString()}`)
router.push(`/home?${params.toString()}`)
}
}}
placeholder={t('search.placeholder') || 'Rechercher...'}
@@ -569,7 +568,7 @@ export function HomeClient({ initialNotes, initialSettings }: HomeClientProps) {
setInlineSearchQuery('')
const params = new URLSearchParams(searchParams.toString())
params.delete('search')
router.push(`/?${params.toString()}`)
router.push(`/home?${params.toString()}`)
}}
className="text-muted-foreground hover:text-foreground transition-colors"
>
@@ -837,6 +836,5 @@ export function HomeClient({ initialNotes, initialSettings }: HomeClientProps) {
/>
)}
</div>
</PageEntry>
)
}

View File

@@ -100,10 +100,10 @@ export function LabHeader({ canvases, currentCanvasId, onCreateCanvas }: LabHead
<ChevronDown className="h-4 w-4 text-muted-foreground ms-2" />
</Button>
</DropdownMenuTrigger>
<DropdownMenuContent align="start" className="w-[280px] p-2 rounded-2xl shadow-xl border-muted/20">
<DropdownMenuContent align="start" className="w-[280px] p-2 rounded-2xl shadow-xl border-border/40 bg-paper dark:bg-dark-paper">
<DropdownMenuLabel className="text-xs text-muted-foreground px-2 py-1.5 flex justify-between items-center">
{t('labHeader.yourSpaces')}
<span className="text-[10px] bg-muted px-1.5 py-0.5 rounded-full font-mono">{canvases.length}</span>
<span className="text-[10px] bg-brand-accent/10 text-brand-accent px-1.5 py-0.5 rounded-full font-mono">{canvases.length}</span>
</DropdownMenuLabel>
<div className="space-y-1 mt-1">
{canvases.map(c => (
@@ -111,13 +111,13 @@ export function LabHeader({ canvases, currentCanvasId, onCreateCanvas }: LabHead
<DropdownMenuItem
className={cn(
"flex-1 flex flex-col items-start gap-0.5 rounded-xl cursor-pointer p-3 transition-all",
c.id === currentCanvasId ? "bg-primary/5 text-primary border border-primary/20" : "hover:bg-muted"
c.id === currentCanvasId ? "bg-brand-accent/5 text-brand-accent border border-brand-accent/20" : "hover:bg-muted/50"
)}
onClick={() => router.push(`/lab?id=${c.id}`)}
>
<div className="flex items-center gap-2 w-full justify-between">
<span className="font-semibold text-sm">{c.name}</span>
{c.id === currentCanvasId && <span className="w-2 h-2 rounded-full bg-primary" />}
{c.id === currentCanvasId && <span className="w-2 h-2 rounded-full bg-brand-accent" />}
</div>
<span className="text-[10px] text-muted-foreground">{t('labHeader.updated')} {new Date(c.updatedAt).toLocaleDateString()}</span>
</DropdownMenuItem>
@@ -139,7 +139,7 @@ export function LabHeader({ canvases, currentCanvasId, onCreateCanvas }: LabHead
<DropdownMenuItem
onClick={handleCreate}
disabled={isPending}
className="flex items-center gap-2 text-primary font-medium p-3 rounded-xl cursor-pointer hover:bg-primary/5"
className="flex items-center gap-2 text-brand-accent font-medium p-3 rounded-xl cursor-pointer hover:bg-brand-accent/5"
>
<Plus className="h-4 w-4" />
{t('labHeader.newSpace')}

View File

@@ -0,0 +1,412 @@
'use client'
import { motion } from 'motion/react'
import {
BrainCircuit, Search, MessageSquare, Zap, Cpu, Workflow,
Globe, Shield, ArrowRight, Sparkles, Layers, Activity,
Box
} from 'lucide-react'
import { useRouter } from 'next/navigation'
import { useLanguage } from '@/lib/i18n'
import { useState } from 'react'
export function LandingPage() {
const { t } = useLanguage()
const router = useRouter()
const [billingInterval, setBillingInterval] = useState<'monthly' | 'annual'>('monthly')
const AGENTS = [
{ key: 'scraper', icon: <Globe size={24} /> },
{ key: 'researcher', icon: <Search size={24} /> },
{ key: 'slideGen', icon: <Layers size={24} /> },
{ key: 'monitor', icon: <Activity size={24} /> },
{ key: 'diagramGen', icon: <Box size={24} /> },
{ key: 'custom', icon: <Workflow size={24} /> },
]
const BRAINSTORM_ITEMS = ['waveGeneration', 'collaboration', 'export']
const PLANS = [
{ key: 'basic', popular: false, price: t('landing.pricing.basicPrice'), period: '' },
{ key: 'pro', popular: true, price: billingInterval === 'monthly' ? '9,90€' : '7,90€', period: billingInterval === 'monthly' ? t('landing.pricing.perMonth') : t('landing.pricing.perMonthAnnual') },
{ key: 'business', popular: false, price: billingInterval === 'monthly' ? '29,90€' : '23,90€', period: billingInterval === 'monthly' ? t('landing.pricing.perMonth') : t('landing.pricing.perMonthAnnual') },
{ key: 'enterprise', popular: false, price: billingInterval === 'monthly' ? '49,90€' : '39,90€', period: billingInterval === 'monthly' ? t('landing.pricing.perUser') : t('landing.pricing.perUserAnnual') },
]
const TECH_TIERS = [
{ key: 'tags', color: 'bg-brand-accent' },
{ key: 'embeddings', color: 'bg-ochre' },
{ key: 'chatRag', color: 'bg-ink' },
]
const FOOTER_SECTIONS = ['product', 'community', 'legal'] as const
return (
<div className="min-h-screen bg-paper text-ink font-sans selection:bg-ochre/30 selection:text-ink">
{/* Navigation */}
<nav className="fixed top-0 left-0 right-0 z-[100] bg-paper/80 backdrop-blur-md border-b border-border px-8 py-4 flex items-center justify-between">
<div className="flex items-center gap-3">
<div className="w-10 h-10 bg-ink flex items-center justify-center rounded-xl shadow-lg rotate-3 group hover:rotate-0 transition-transform cursor-pointer">
<span className="text-paper font-serif text-2xl font-bold">M</span>
</div>
<span className="font-serif text-2xl font-medium tracking-tight">Momento</span>
</div>
<div className="hidden md:flex items-center gap-10">
<a href="#features" className="text-[11px] font-bold uppercase tracking-widest text-concrete hover:text-ink transition-colors">{t('landing.nav.features')}</a>
<a href="#agents" className="text-[11px] font-bold uppercase tracking-widest text-concrete hover:text-ink transition-colors">{t('landing.nav.agents')}</a>
<a href="#brainstorm" className="text-[11px] font-bold uppercase tracking-widest text-concrete hover:text-ink transition-colors">{t('landing.nav.brainstorm')}</a>
<a href="#pricing" className="text-[11px] font-bold uppercase tracking-widest text-concrete hover:text-ink transition-colors">{t('landing.nav.pricing')}</a>
<a href="#tech" className="text-[11px] font-bold uppercase tracking-widest text-concrete hover:text-ink transition-colors">{t('landing.nav.tech')}</a>
</div>
<div className="flex items-center gap-4">
<button onClick={() => router.push('/login')} className="hidden md:block px-6 py-2.5 text-concrete hover:text-ink text-[11px] font-bold uppercase tracking-widest transition-colors">
{t('landing.nav.login')}
</button>
<button onClick={() => router.push('/register')} className="px-6 py-2.5 bg-ink text-paper rounded-full text-[11px] font-bold uppercase tracking-widest hover:opacity-90 transition-all flex items-center gap-2 group shadow-xl shadow-ink/10">
{t('landing.nav.cta')}
<ArrowRight size={14} className="group-hover:translate-x-1 transition-transform" />
</button>
</div>
</nav>
{/* Hero */}
<section className="relative pt-40 pb-32 px-8 overflow-hidden">
<div className="absolute top-0 right-0 w-[800px] h-[800px] bg-ochre/5 rounded-full blur-[120px] -translate-y-1/2 translate-x-1/4 -z-10" />
<div className="absolute bottom-0 left-0 w-[600px] h-[600px] bg-brand-accent/5 rounded-full blur-[100px] translate-y-1/2 -translate-x-1/4 -z-10" />
<div className="max-w-6xl mx-auto text-center">
<motion.div initial={{ opacity: 0, y: 30 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 0.8, ease: [0.23, 1, 0.32, 1] }}>
<div className="inline-flex items-center gap-2 px-4 py-1.5 rounded-full bg-ochre/10 border border-ochre/20 text-ochre text-[10px] font-bold uppercase tracking-[0.2em] mb-8">
<Sparkles size={12} />
{t('landing.hero.badge')}
</div>
<h1 className="text-6xl md:text-8xl font-serif font-medium tracking-tight text-ink mb-8 leading-[1.1]">
{t('landing.hero.title1')} <br />
<span className="italic">{t('landing.hero.title2')}</span>
</h1>
<p className="max-w-2xl mx-auto text-lg md:text-xl text-concrete font-light leading-relaxed mb-12">
{t('landing.hero.subtitle')}
</p>
<div className="flex flex-col sm:flex-row items-center justify-center gap-4">
<button onClick={() => router.push('/register')} className="px-10 py-5 bg-ink text-paper rounded-2xl text-sm font-bold uppercase tracking-[0.2em] hover:opacity-95 transition-all shadow-2xl shadow-ink/20 flex items-center gap-4 group">
{t('landing.hero.cta')}
<ArrowRight size={18} className="group-hover:translate-x-1 transition-transform" />
</button>
<a href="#features" className="px-10 py-5 border border-border rounded-2xl text-sm font-bold uppercase tracking-[0.2em] hover:bg-slate-50 transition-all">
{t('landing.hero.secondary')}
</a>
</div>
</motion.div>
{/* App Preview Mockup */}
<motion.div initial={{ opacity: 0, y: 100 }} animate={{ opacity: 1, y: 0 }} transition={{ duration: 1, delay: 0.2, ease: [0.23, 1, 0.32, 1] }} className="mt-24 relative">
<div className="relative mx-auto max-w-5xl aspect-[16/10] bg-white rounded-[32px] shadow-[0_40px_100px_-20px_rgba(0,0,0,0.15)] border border-border p-4 overflow-hidden group">
<img src="/images/workspace-hero.jpg" alt="Momento Workspace" className="w-full h-full object-cover rounded-2xl filter saturate-[0.8]" />
<div className="absolute inset-0 bg-ink/10 group-hover:bg-ink/0 transition-colors duration-500" />
<div className="absolute top-10 right-10 w-64 bg-paper/90 backdrop-blur-xl border border-border p-6 rounded-2xl shadow-2xl">
<div className="flex items-center gap-3 mb-4">
<div className="w-8 h-8 rounded-full bg-brand-accent/20 flex items-center justify-center text-brand-accent">
<BrainCircuit size={16} />
</div>
<span className="text-[10px] font-bold uppercase tracking-widest">{t('landing.hero.memoryEcho')}</span>
</div>
<p className="text-xs font-serif italic text-ink/70">{t('landing.hero.memoryEchoText')}</p>
</div>
<div className="absolute bottom-10 left-10 w-72 bg-ink text-paper p-6 rounded-2xl shadow-2xl">
<div className="flex items-center gap-3 mb-4">
<Activity size={16} className="text-ochre" />
<span className="text-[10px] font-bold uppercase tracking-widest text-ochre">{t('landing.hero.brainstormLive')}</span>
</div>
<div className="flex items-center -space-x-2">
{[1, 2, 3].map(i => (
<div key={i} className="w-6 h-6 rounded-full border-2 border-ink bg-concrete text-[8px] flex items-center justify-center font-bold">JD</div>
))}
<span className="text-[10px] ml-4 text-paper/60">{t('landing.hero.ideasGenerated')}</span>
</div>
</div>
</div>
</motion.div>
</div>
</section>
{/* Features */}
<section id="features" className="py-32 px-8 bg-paper">
<div className="max-w-6xl mx-auto">
<div className="mb-24 flex flex-col md:flex-row md:items-end justify-between gap-8">
<div className="max-w-2xl">
<span className="text-[11px] font-bold uppercase tracking-[0.3em] text-ochre mb-4 block">{t('landing.features.label')}</span>
<h2 className="text-4xl md:text-5xl font-serif tracking-tight text-ink">{t('landing.features.title')} <br />{t('landing.features.title2')}</h2>
</div>
<div className="text-concrete font-light">{t('landing.features.desc')}</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-3 gap-12">
{['f1', 'f2', 'f3'].map((f, i) => {
const icons = [
<Search key="s" className="text-brand-accent" />,
<MessageSquare key="m" className="text-ochre" />,
<Zap key="z" className="text-ink" />
]
return (
<div key={f} className="group">
<div className="w-14 h-14 bg-slate-50 border border-border rounded-2xl flex items-center justify-center mb-8 group-hover:bg-ink group-hover:text-paper transition-all duration-300">
{icons[i]}
</div>
<h3 className="text-xl font-serif font-medium mb-4">{t(`landing.features.${f}Title`)}</h3>
<p className="text-sm text-concrete leading-relaxed font-light">{t(`landing.features.${f}Desc`)}</p>
</div>
)
})}
</div>
</div>
</section>
{/* Agents */}
<section id="agents" className="py-32 px-8 bg-ink text-paper overflow-hidden relative">
<div className="absolute top-0 right-0 w-[1000px] h-[1000px] bg-brand-accent/10 rounded-full blur-[150px] -translate-y-1/2 translate-x-1/2" />
<div className="max-w-6xl mx-auto relative z-10">
<div className="text-center mb-24">
<span className="text-[11px] font-bold uppercase tracking-[0.3em] text-ochre mb-4 block">{t('landing.agents.label')}</span>
<h2 className="text-4xl md:text-6xl font-serif tracking-tight mb-8">{t('landing.agents.title')}</h2>
<p className="text-paper/60 max-w-xl mx-auto font-light">{t('landing.agents.desc')}</p>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-3 gap-8">
{AGENTS.map((agent, i) => (
<div key={i} className="p-8 rounded-3xl bg-white/5 border border-white/10 hover:bg-white/10 transition-all cursor-default group">
<div className="text-ochre mb-6 transition-transform group-hover:scale-110 duration-300">{agent.icon}</div>
<h4 className="text-xl font-serif font-medium mb-4">{t(`landing.agents.${agent.key}.title`)}</h4>
<p className="text-sm text-paper/50 leading-relaxed font-light">{t(`landing.agents.${agent.key}.desc`)}</p>
</div>
))}
</div>
</div>
</section>
{/* Brainstorm */}
<section id="brainstorm" className="py-32 px-8 bg-paper">
<div className="max-w-6xl mx-auto flex flex-col md:flex-row items-center gap-24">
<div className="flex-1">
<span className="text-[11px] font-bold uppercase tracking-[0.3em] text-ochre mb-4 block">{t('landing.brainstorm.label')}</span>
<h2 className="text-4xl md:text-5xl font-serif tracking-tight text-ink mb-8 leading-tight">{t('landing.brainstorm.title')}</h2>
<div className="space-y-8">
{BRAINSTORM_ITEMS.map((item, i) => (
<div key={item} className="flex gap-6">
<div className="flex-shrink-0 w-8 h-8 rounded-full bg-ochre/10 text-ochre flex items-center justify-center font-bold text-xs">{i + 1}</div>
<div>
<h5 className="font-bold text-sm mb-1">{t(`landing.brainstorm.${item}.title`)}</h5>
<p className="text-sm text-concrete font-light leading-relaxed">{t(`landing.brainstorm.${item}.desc`)}</p>
</div>
</div>
))}
</div>
</div>
<div className="flex-1 relative">
<div className="w-[450px] h-[450px] border-2 border-dashed border-border rounded-full flex items-center justify-center relative">
<div className="absolute top-0 right-1/2 translate-x-1/2 -translate-y-1/2 w-4 h-4 bg-ink rounded-full" />
<div className="absolute bottom-0 right-1/2 translate-x-1/2 translate-y-1/2 w-4 h-4 bg-ochre rounded-full" />
<div className="w-[300px] h-[300px] border-2 border-dashed border-border rounded-full flex items-center justify-center">
<div className="w-[150px] h-[150px] border-2 border-dashed border-border rounded-full flex items-center justify-center">
<div className="w-12 h-12 bg-ink rounded-xl shadow-2xl flex items-center justify-center text-paper font-serif text-xl">M</div>
</div>
</div>
</div>
<div className="absolute top-10 right-0 p-4 bg-white border border-border rounded-xl shadow-xl">
<p className="text-[10px] font-bold text-ochre">{t('landing.brainstorm.disruptionLabel')}</p>
<p className="text-xs font-serif italic text-ink">{t('landing.brainstorm.disruptionText')}</p>
</div>
<div className="absolute bottom-20 -left-10 p-4 bg-white border border-border rounded-xl shadow-xl">
<p className="text-[10px] font-bold text-brand-accent">{t('landing.brainstorm.analogyLabel')}</p>
<p className="text-xs font-serif italic text-ink">{t('landing.brainstorm.analogyText')}</p>
</div>
</div>
</div>
</section>
{/* Tech */}
<section id="tech" className="py-32 px-8 bg-slate-50 border-y border-border">
<div className="max-w-6xl mx-auto text-center">
<span className="text-[11px] font-bold uppercase tracking-[0.3em] text-ochre mb-4 block">{t('landing.tech.label')}</span>
<h2 className="text-4xl font-serif tracking-tight mb-16">{t('landing.tech.title')}</h2>
<div className="grid grid-cols-2 md:grid-cols-4 lg:grid-cols-6 gap-8 grayscale opacity-50 hover:grayscale-0 hover:opacity-100 transition-all duration-700">
{['OpenAI', 'Google', 'Anthropic', 'DeepSeek', 'Mistral', 'Meta', 'Ollama', 'Groq', 'X.AI', 'Custom'].map((brand, i) => (
<div key={i} className="flex flex-col items-center gap-3">
<div className="w-12 h-12 bg-white rounded-xl border border-border flex items-center justify-center text-xs font-black tracking-tighter">
{brand.slice(0, 2).toUpperCase()}
</div>
<span className="text-[10px] font-bold uppercase tracking-widest">{brand}</span>
</div>
))}
</div>
<div className="mt-24 max-w-2xl mx-auto p-1 bg-white rounded-3xl border border-border shadow-sm flex flex-col md:flex-row gap-0.5">
{TECH_TIERS.map((tier, i) => (
<div key={i} className="flex-1 p-6 text-left">
<div className={`w-1.5 h-1.5 rounded-full ${tier.color} mb-4`} />
<h6 className="text-[10px] font-bold uppercase tracking-widest text-concrete mb-2">{t(`landing.tech.${tier.key}.title`)}</h6>
<p className="text-xs font-light text-concrete">{t(`landing.tech.${tier.key}.desc`)}</p>
</div>
))}
</div>
</div>
</section>
{/* Pricing */}
<section id="pricing" className="py-32 px-8 bg-paper">
<div className="max-w-7xl mx-auto">
<div className="text-center mb-12">
<span className="text-[11px] font-bold uppercase tracking-[0.3em] text-ochre mb-4 block">{t('landing.pricing.label')}</span>
<h2 className="text-4xl md:text-5xl font-serif tracking-tight text-ink mb-6">{t('landing.pricing.title')}</h2>
<p className="text-concrete font-light max-w-xl mx-auto mb-12">{t('landing.pricing.desc')}</p>
<div className="flex items-center justify-center gap-10 mb-8">
<button onClick={() => setBillingInterval('monthly')} className={`group relative py-2 px-1 transition-all ${billingInterval === 'monthly' ? 'text-ink' : 'text-concrete/40 hover:text-concrete'}`}>
<span className="text-xs font-black uppercase tracking-[0.2em]">{t('landing.pricing.monthly')}</span>
{billingInterval === 'monthly' && (
<motion.div layoutId="interval-active" className="absolute -inset-x-1 -inset-y-0.5 border border-ochre/60" transition={{ type: 'spring', bounce: 0.2, duration: 0.6 }} />
)}
</button>
<div className="relative">
<button onClick={() => setBillingInterval('annual')} className={`group relative py-2 px-1 transition-all ${billingInterval === 'annual' ? 'text-ink' : 'text-concrete/40 hover:text-concrete'}`}>
<span className="text-xs font-black uppercase tracking-[0.2em]">{t('landing.pricing.annual')}</span>
{billingInterval === 'annual' && (
<motion.div layoutId="interval-active" className="absolute -inset-x-1 -inset-y-0.5 border border-ochre/60" transition={{ type: 'spring', bounce: 0.2, duration: 0.6 }} />
)}
</button>
<div className="absolute -top-6 left-1/2 -translate-x-1/2 whitespace-nowrap">
<span className="text-[9px] font-bold text-ochre uppercase tracking-widest italic animate-pulse">(-20%)</span>
</div>
</div>
</div>
</div>
<div className="grid grid-cols-1 md:grid-cols-2 lg:grid-cols-4 gap-6 items-stretch">
{PLANS.map((plan, i) => (
<div key={plan.key} className={`relative p-8 rounded-[32px] border flex flex-col transition-all duration-300 hover:shadow-2xl hover:shadow-ink/5 ${plan.popular ? 'bg-ink text-paper border-ink ring-4 ring-ochre/20' : 'bg-white border-border text-ink'}`}>
{plan.popular && (
<div className="absolute -top-4 left-1/2 -translate-x-1/2 px-4 py-1 bg-ochre text-ink text-[10px] font-bold uppercase tracking-widest rounded-full">
{t('landing.pricing.popular')}
</div>
)}
<div className="mb-8">
<h4 className="text-[11px] font-bold uppercase tracking-widest mb-2 opacity-60">{t(`landing.pricing.${plan.key}.name`)}</h4>
<div className="flex items-baseline gap-1 mb-4">
<span className="text-4xl font-serif font-medium">{plan.price}</span>
{plan.period && <span className="text-xs opacity-60">{plan.period}</span>}
</div>
<p className="text-sm font-light leading-relaxed opacity-80">{t(`landing.pricing.${plan.key}.desc`)}</p>
</div>
<div className="flex-1 space-y-4 mb-10">
{[0, 1, 2, 3, 4, 5].map(j => {
const feat = t(`landing.pricing.${plan.key}.feature${j}`)
if (!feat || feat === `landing.pricing.${plan.key}.feature${j}`) return null
return (
<div key={j} className="flex items-start gap-3">
<div className={`mt-1 rounded-full p-0.5 ${plan.popular ? 'bg-ochre text-ink' : 'bg-brand-accent/10 text-brand-accent'}`}>
<Shield size={10} fill="currentColor" />
</div>
<span className="text-xs font-light">{feat}</span>
</div>
)
})}
</div>
<button onClick={() => router.push('/register')} className={`w-full py-4 rounded-2xl text-xs font-bold uppercase tracking-widest transition-all ${plan.popular ? 'bg-ochre text-ink hover:opacity-90' : 'bg-ink text-paper hover:bg-ink/90'}`}>
{t(`landing.pricing.${plan.key}.cta`)}
</button>
</div>
))}
</div>
{/* BYOK */}
<div className="mt-20 p-12 bg-slate-50 border border-border rounded-[40px] flex flex-col md:flex-row items-center gap-12">
<div className="flex-1">
<div className="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-brand-accent/10 text-brand-accent text-[9px] font-bold uppercase tracking-widest mb-6">
<Cpu size={12} />
{t('landing.byok.label')}
</div>
<h3 className="text-3xl font-serif font-medium mb-4">{t('landing.byok.title')}</h3>
<p className="text-concrete font-light leading-relaxed mb-6">{t('landing.byok.desc')}</p>
<div className="grid grid-cols-2 gap-4">
<div className="p-4 bg-white rounded-2xl border border-border">
<h5 className="text-[10px] font-bold uppercase tracking-widest mb-2">{t('landing.byok.noLockin')}</h5>
<p className="text-[10px] text-concrete font-light">{t('landing.byok.noLockinDesc')}</p>
</div>
<div className="p-4 bg-white rounded-2xl border border-border">
<h5 className="text-[10px] font-bold uppercase tracking-widest mb-2">{t('landing.byok.cost')}</h5>
<p className="text-[10px] text-concrete font-light">{t('landing.byok.costDesc')}</p>
</div>
</div>
</div>
<div className="w-full md:w-[400px] bg-ink rounded-3xl p-8 relative overflow-hidden group">
<div className="absolute inset-0 bg-brand-accent/10 blur-[50px] group-hover:bg-ochre/10 transition-colors" />
<div className="relative z-10 font-mono text-[10px] text-paper/40 space-y-2">
<p className="text-ochre">{"{"}</p>
<p className="pl-4">"provider": "anthropic",</p>
<p className="pl-4">"model": "claude-3-opus",</p>
<p className="pl-4 border-l border-brand-accent/30 bg-brand-accent/5">"apiKey": "sk-ant-at03-..."</p>
<p className="pl-4">"useSystemKey": false</p>
<p className="text-ochre">{"}"}</p>
</div>
<div className="mt-8 flex items-center justify-between relative z-10">
<span className="text-[10px] font-bold text-paper uppercase tracking-widest">{t('landing.byok.configLabel')}</span>
<div className="flex gap-1">{[1, 2, 3].map(i => <div key={i} className="w-1 h-1 rounded-full bg-paper/20" />)}</div>
</div>
</div>
</div>
</div>
</section>
{/* Final CTA */}
<section className="py-40 px-8 text-center bg-paper relative overflow-hidden">
<div className="max-w-3xl mx-auto relative z-10">
<h2 className="text-5xl md:text-7xl font-serif tracking-tight mb-8 leading-tight">{t('landing.cta.title1')} <br /><span className="italic">{t('landing.cta.title2')}</span></h2>
<p className="text-lg text-concrete font-light mb-12">{t('landing.cta.desc')}</p>
<button onClick={() => router.push('/register')} className="px-16 py-6 bg-ink text-paper rounded-[32px] text-lg font-bold uppercase tracking-[0.2em] hover:scale-105 transition-all shadow-[0_30px_60px_-15px_rgba(0,0,0,0.3)]">
{t('landing.cta.button')}
</button>
</div>
</section>
{/* Footer */}
<footer className="py-20 px-8 border-t border-border bg-paper">
<div className="max-w-6xl mx-auto flex flex-col md:flex-row justify-between gap-12">
<div className="space-y-6">
<div className="flex items-center gap-3">
<div className="w-8 h-8 bg-ink flex items-center justify-center rounded-lg">
<span className="text-paper font-serif text-lg font-bold">M</span>
</div>
<span className="font-serif text-xl font-medium tracking-tight">Momento</span>
</div>
<p className="text-sm text-concrete font-light max-w-xs">{t('landing.footer.desc')}</p>
</div>
<div className="grid grid-cols-2 md:grid-cols-3 gap-16">
{FOOTER_SECTIONS.map(section => (
<div key={section} className="space-y-4">
<h6 className="text-[10px] font-bold uppercase tracking-widest text-ink">{t(`landing.footer.${section}.title`)}</h6>
<ul className="space-y-2 text-sm text-concrete font-light">
{[0, 1, 2].map(j => {
const label = t(`landing.footer.${section}.link${j}`)
const href = t(`landing.footer.${section}.link${j}Href`)
if (!label || label.startsWith('landing.')) return null
return <li key={j}><a href={href} className="hover:text-ink">{label}</a></li>
})}
</ul>
</div>
))}
</div>
</div>
<div className="max-w-6xl mx-auto mt-20 pt-10 border-t border-border flex flex-col md:flex-row justify-between items-center gap-4 text-[10px] uppercase font-bold tracking-widest text-concrete">
<div>© 2026 MOMENTO LABS. ALL RIGHTS RESERVED.</div>
<div className="flex gap-8"><span>DESIGNED BY ANTIGRAVITY</span></div>
</div>
</footer>
</div>
)
}

View File

@@ -116,7 +116,7 @@ export function NoteEditorDialog({ onClose }: NoteEditorDialogProps) {
noteId={note.id}
onOpenNote={(noteId: string) => {
onClose()
window.location.href = `/?note=${noteId}`
window.location.href = `/home?note=${noteId}`
}}
onCompareNotes={(noteIds: string[]) => {
Promise.all(noteIds.map(async (id: string) => {
@@ -296,7 +296,7 @@ export function NoteEditorDialog({ onClose }: NoteEditorDialogProps) {
notes={state.comparisonNotes}
onOpenNote={(noteId: string) => {
onClose()
window.location.href = `/?note=${noteId}`
window.location.href = `/home?note=${noteId}`
}}
/>
)}

View File

@@ -177,23 +177,23 @@ export function NotificationPanel() {
// ── icon bg/color per notification type ──────────────────────────────────
const notifIconStyle = (type: string) => {
if (type === 'agent_success') return { bg: `${C.gold}20`, color: C.gold }
if (type === 'agent_slides_ready') return { bg: `${C.gold}20`, color: C.gold }
if (type === 'agent_canvas_ready') return { bg: `${C.gold}20`, color: C.gold }
if (type === 'agent_failure') return { bg: '#EF444420', color: '#EF4444' }
if (type === 'brainstorm_invite') return { bg: '#10b98120', color: '#10b981' }
if (type === 'brainstorm_joined') return { bg: '#60a5fa20', color: '#60a5fa' }
return { bg: `${C.green}20`, color: C.green }
if (type === 'agent_success') return { bg: 'rgba(164,113,72,0.12)', color: '#A47148' }
if (type === 'agent_slides_ready') return { bg: 'rgba(164,113,72,0.12)', color: '#A47148' }
if (type === 'agent_canvas_ready') return { bg: 'rgba(164,113,72,0.12)', color: '#A47148' }
if (type === 'agent_failure') return { bg: 'rgba(239,68,68,0.12)', color: '#EF4444' }
if (type === 'brainstorm_invite') return { bg: 'rgba(163,177,138,0.12)', color: '#A3B18A' }
if (type === 'brainstorm_joined') return { bg: 'rgba(163,177,138,0.12)', color: '#A3B18A' }
return { bg: 'rgba(163,177,138,0.12)', color: '#A3B18A' }
}
const notifLabelColor = (type: string) => {
if (type.startsWith('agent')) {
if (type === 'agent_failure') return '#EF4444'
if (type === 'brainstorm_invite') return '#10b981'
if (type === 'brainstorm_joined') return '#60a5fa'
return C.gold
if (type === 'brainstorm_invite') return '#A3B18A'
if (type === 'brainstorm_joined') return '#A3B18A'
return '#A47148'
}
return C.green
return '#A3B18A'
}
return (
@@ -205,8 +205,7 @@ export function NotificationPanel() {
<Bell className="h-4 w-4 transition-transform duration-200 hover:scale-110" />
{pendingCount > 0 && (
<span
className="absolute -top-1 -right-1 h-4 w-4 flex items-center justify-center rounded-full text-white text-[9px] font-bold border border-white shadow-sm"
style={{ background: C.green }}
className="absolute -top-1 -right-1 h-4 w-4 flex items-center justify-center rounded-full text-white text-[9px] font-bold border border-white shadow-sm bg-brand-accent"
>
{pendingCount > 9 ? '9+' : pendingCount}
</span>
@@ -235,8 +234,7 @@ export function NotificationPanel() {
)}
{pendingCount > 0 && (
<span
className="h-5 px-1.5 flex items-center justify-center rounded-full text-white text-[9px] font-bold"
style={{ background: C.green }}
className="h-5 px-1.5 flex items-center justify-center rounded-full text-white text-[9px] font-bold bg-brand-accent"
>
{pendingCount}
</span>
@@ -405,14 +403,14 @@ export function NotificationPanel() {
<div className="flex items-start gap-3">
<div
className="h-8 w-8 rounded-full flex items-center justify-center text-white font-bold text-[11px] shrink-0 shadow-sm"
style={{ background: `linear-gradient(135deg, #fb923c, #f97316)` }}
style={{ background: `linear-gradient(135deg, #A47148, #A47148)` }}
>
{(share.sharer?.name || share.sharer?.email || '?')[0].toUpperCase()}
</div>
<div className="flex-1 min-w-0">
<div className="flex items-center gap-1.5 mb-0.5">
<Wind className="w-3 h-3" style={{ color: '#fb923c' }} />
<span className="text-[9px] font-bold uppercase tracking-[0.2em]" style={{ color: '#fb923c' }}>
<Wind className="w-3 h-3" style={{ color: '#A47148' }} />
<span className="text-[9px] font-bold uppercase tracking-[0.2em]" style={{ color: '#A47148' }}>
Brainstorm
</span>
</div>
@@ -434,8 +432,7 @@ export function NotificationPanel() {
</button>
<button
onClick={() => handleAcceptBrainstorm(share.id)}
className="flex-1 h-7 px-3 text-[11px] font-bold rounded-lg text-white transition-all active:scale-95 flex items-center justify-center gap-1 shadow-sm hover:opacity-90"
style={{ background: '#fb923c' }}
className="flex-1 h-7 px-3 text-[11px] font-bold rounded-lg text-white transition-all active:scale-95 flex items-center justify-center gap-1 shadow-sm hover:opacity-90 bg-brand-accent"
>
<Check className="h-3 w-3" />
{t('notification.accept') || 'Accept'}

View File

@@ -1,16 +0,0 @@
'use client'
import { motion } from 'motion/react'
export function PageEntry({ children, className }: { children: React.ReactNode; className?: string }) {
return (
<motion.div
initial={{ opacity: 0, y: 6 }}
animate={{ opacity: 1, y: 0 }}
transition={{ duration: 0.25, ease: [0.23, 1, 0.32, 1] }}
className={className}
>
{children}
</motion.div>
)
}

View File

@@ -1,9 +0,0 @@
'use client'
export function PageTransition({ children }: { children: React.ReactNode }) {
return (
<div className="flex-1 flex flex-col min-h-0">
{children}
</div>
)
}

View File

@@ -0,0 +1,41 @@
'use client'
import { LanguageProvider, useLanguage } from '@/lib/i18n/LanguageProvider'
import { QueryProvider } from '@/components/query-provider'
import type { Translations } from '@/lib/i18n/load-translations'
import type { ReactNode } from 'react'
import { useEffect } from 'react'
const RTL_LANGUAGES = ['ar', 'fa']
function DirWrapper({ children }: { children: ReactNode }) {
const { language } = useLanguage()
const dir = RTL_LANGUAGES.includes(language) ? 'rtl' : 'ltr'
useEffect(() => {
document.documentElement.lang = language
document.documentElement.dir = dir
}, [language, dir])
return <div dir={dir} className="contents">{children}</div>
}
export function PublicProviders({
children,
initialLanguage = 'en',
initialTranslations
}: {
children: ReactNode
initialLanguage?: string
initialTranslations?: Translations
}) {
return (
<QueryProvider>
<LanguageProvider initialLanguage={initialLanguage as any} initialTranslations={initialTranslations}>
<DirWrapper>
{children}
</DirWrapper>
</LanguageProvider>
</QueryProvider>
)
}

View File

@@ -150,7 +150,22 @@ async function aiReformulate(text: string, option: string, language?: string): P
})
const data = await res.json()
if (!res.ok) {
const serverMsg = typeof data?.error === 'string' && data.error.trim() ? data.error.trim() : AI_REFORMULATE_FALLBACK
if (data?.errorKey === 'ai.wordCountMin') {
throw new Error(t('ai.wordCountMin') || `Minimum ${data?.params?.min || 10} mots requis (${data?.params?.current || 0} actuels)`)
}
if (data?.errorKey === 'ai.wordCountMax') {
throw new Error(t('ai.wordCountMax') || `Maximum ${data?.params?.max || 500} mots (${data?.params?.current || 0} actuels)`)
}
if (data?.errorKey === 'ai.featureLocked') {
throw new Error(t('ai.featureLocked') || 'Cette fonctionnalité nécessite le plan PRO.')
}
if (data?.errorKey === 'ai.quotaExceeded') {
throw new Error(t('ai.quotaExceeded') || 'Limite mensuelle atteinte.')
}
if (data?.quotaExceeded) {
throw new Error(t('ai.quotaExceeded') || 'Limite mensuelle atteinte.')
}
const serverMsg = typeof data?.error === 'string' && !data.error.includes(':') ? data.error.trim() : AI_REFORMULATE_FALLBACK
throw new Error(serverMsg)
}
return data.reformulatedText || data.text || text
@@ -385,6 +400,7 @@ function BubbleToolbar({ editor }: { editor: Editor | null }) {
try {
const lang = option === 'translate' ? (targetLang || language) : language
const result = await aiReformulate(text, option, lang)
window.dispatchEvent(new Event('ai-usage-changed'))
if (option === 'explain') {
setAiModal({ type: 'explain', origText: text, html: result, from, to })
} else {

View File

@@ -28,12 +28,12 @@ export function SettingsNav({ className }: SettingsNavProps) {
const isActive = (href: string) => pathname === href || pathname.startsWith(href + '/')
return (
<nav className={`flex items-center gap-1 border-b border-border/40 pb-px ${className || ''}`}>
<nav className={`flex flex-wrap items-center gap-1 border-b border-border/40 pb-px ${className || ''}`}>
{tabs.map((tab) => (
<Link
key={tab.id}
href={tab.href}
className="flex items-center gap-2.5 px-6 py-5 text-[10px] font-bold uppercase tracking-[0.18em] transition-all relative whitespace-nowrap text-concrete hover:text-ink/60"
className="flex items-center gap-2.5 px-4 py-3 text-[10px] font-bold uppercase tracking-[0.18em] transition-all relative whitespace-nowrap text-concrete hover:text-ink/60"
style={{ color: isActive(tab.href) ? 'var(--ink)' : undefined }}
>
<span style={{ color: isActive(tab.href) ? 'var(--ink)' : 'var(--concrete)' }}>{tab.icon}</span>

View File

@@ -234,7 +234,7 @@ export function BillingPlans() {
{/* Usage Overview */}
<div className="grid grid-cols-1 md:grid-cols-2 gap-6">
<div className="bg-white/40 dark:bg-white/5 border border-border rounded-3xl p-8 space-y-6">
<div className="md:col-span-2 bg-white/40 dark:bg-white/5 border border-border rounded-3xl p-8 space-y-6">
<div className="flex items-center gap-4">
<div className="p-2 bg-brand-accent/10 text-brand-accent rounded-xl">
<Activity size={20} />
@@ -243,18 +243,57 @@ export function BillingPlans() {
<h4 className="text-sm font-bold text-ink">{t('billing.currentUsage') || 'Utilisation actuelle'}</h4>
<p className="text-[10px] text-concrete uppercase tracking-widest">{t('billing.currentPeriod') || 'Période en cours'}</p>
</div>
</div>
<div className="space-y-4">
<div className="space-y-2">
<div className="flex justify-between text-[11px] font-medium text-concrete uppercase tracking-wider">
<span>{t('billing.aiCredits') || 'Crédits IA'}</span>
<span>{aiUsed} / {aiLimit} {t('billing.used') || 'utilisés'}</span>
</div>
<div className="h-2 w-full bg-slate-100 dark:bg-white/5 rounded-full overflow-hidden">
<div className="h-full bg-brand-accent rounded-full" style={{ width: `${aiPct}%` }} />
</div>
<div className="ml-auto">
<span className={cn(
'px-3 py-1 rounded-full text-[10px] font-bold uppercase tracking-widest',
isPaid ? 'bg-brand-accent/10 text-brand-accent' : 'bg-concrete/10 text-concrete'
)}>
{effectiveTier === 'BASIC' ? 'Discovery' : effectiveTier}
</span>
</div>
</div>
<div className="grid grid-cols-2 md:grid-cols-3 lg:grid-cols-4 gap-4">
{!quotas && (
<div className="col-span-full flex items-center justify-center py-8">
<Loader2 className="h-5 w-5 animate-spin text-concrete" />
</div>
)}
{quotas && Object.entries(quotas).filter(([_, q]) => q.limit > 0).length === 0 && (
<p className="col-span-full text-xs text-concrete text-center py-4">Aucune donnée d'utilisation disponible</p>
)}
{quotas && Object.entries(quotas).filter(([_, q]) => q.limit > 0).map(([key, q]) => {
const pct = q.limit > 0 ? (q.used / q.limit) * 100 : 0
const featureLabels: Record<string, string> = {
semantic_search: t('usageMeter.featureSearch'),
auto_tag: t('usageMeter.featureTags'),
auto_title: t('usageMeter.featureTitles'),
reformulate: t('usageMeter.featureReformulate'),
chat: t('usageMeter.featureChat'),
brainstorm_create: t('usageMeter.featureBrainstormCreate'),
brainstorm_expand: t('usageMeter.featureBrainstormExpand'),
brainstorm_enrich: t('usageMeter.featureBrainstormEnrich'),
}
return (
<div key={key} className="space-y-2 p-3 rounded-xl bg-paper/50 dark:bg-white/5">
<div className="flex justify-between items-center">
<span className="text-[10px] font-bold text-concrete uppercase tracking-wider truncate">
{featureLabels[key] || key}
</span>
</div>
<div className="flex items-baseline gap-1">
<span className="text-lg font-bold text-ink">{q.remaining === Infinity ? '' : q.remaining}</span>
<span className="text-[10px] text-concrete">/ {q.limit === Infinity ? '' : q.limit}</span>
</div>
<div className="h-1.5 w-full bg-slate-100 dark:bg-white/5 rounded-full overflow-hidden">
<div
className={cn('h-full rounded-full transition-all', pct >= 90 ? 'bg-rose-500' : pct >= 70 ? 'bg-amber-500' : 'bg-brand-accent')}
style={{ width: `${Math.min(pct, 100)}%` }}
/>
</div>
</div>
)
})}
</div>
</div>
<div className="bg-white/40 dark:bg-white/5 border border-border rounded-3xl p-8 space-y-6">

View File

@@ -469,7 +469,7 @@ export function Sidebar({ className, user }: { className?: string; user?: any })
const currentNoteId = searchParams.get('openNote')
const isInboxActive =
pathname === '/' &&
pathname === '/home' &&
!searchParams.get('notebook') &&
!searchParams.get('labels') &&
!searchParams.get('archived') &&
@@ -534,11 +534,11 @@ export function Sidebar({ className, user }: { className?: string; user?: any })
const params = new URLSearchParams()
params.set('notebook', notebookId)
params.set('forceList', '1')
router.push(`/?${params.toString()}`)
router.push(`/home?${params.toString()}`)
}
const handleInboxClick = () => {
router.push('/?forceList=1')
router.push('/home?forceList=1')
}
const handleNoteClick = (noteId: string, notebookId: string) => {
@@ -546,7 +546,7 @@ export function Sidebar({ className, user }: { className?: string; user?: any })
params.set('notebook', notebookId)
params.set('openNote', noteId)
params.delete('forceList')
router.push(`/?${params.toString()}`)
router.push(`/home?${params.toString()}`)
}
// ── Drag state ──
@@ -706,7 +706,7 @@ export function Sidebar({ className, user }: { className?: string; user?: any })
await trashNotebook(deletingNotebook.id)
setDeletingNotebook(null)
if (currentNotebookId === deletingNotebook.id) {
router.push('/')
router.push('/home')
}
} catch (err) {
console.error('Trash failed:', err)
@@ -871,7 +871,7 @@ export function Sidebar({ className, user }: { className?: string; user?: any })
<Settings size={14} />
</Link>
<button
onClick={() => { router.push('/') }}
onClick={() => { router.push('/home') }}
className="p-1.5 text-muted-ink hover:text-ink transition-all hover:bg-white/50 dark:hover:bg-white/10 rounded-lg border border-transparent hover:border-border"
title={t('nav.home') || 'Accueil'}
>
@@ -889,29 +889,29 @@ export function Sidebar({ className, user }: { className?: string; user?: any })
<div className="flex bg-white/50 dark:bg-white/10 p-1 rounded-xl border border-border dark:border-white/10">
<button
onClick={() => { setActiveView('notebooks'); if (pathname !== '/') router.push('/') }}
className={cn('flex-1 flex items-center justify-center py-1.5 rounded-lg transition-all', activeView === 'notebooks' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink hover:bg-white/50')}
onClick={() => { setActiveView('notebooks'); if (pathname !== '/home') router.push('/home') }}
className={cn('flex-1 flex items-center justify-center py-1.5 rounded-lg transition-all', activeView === 'notebooks' ? 'bg-brand-accent text-white shadow-sm' : 'text-muted-ink hover:text-ink hover:bg-white/50')}
title={t('nav.notebooks')}
>
<BookOpen size={14} />
</button>
<button
onClick={() => setActiveView('reminders')}
className={cn('flex-1 flex items-center justify-center py-1.5 rounded-lg transition-all', activeView === 'reminders' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink hover:bg-white/50')}
className={cn('flex-1 flex items-center justify-center py-1.5 rounded-lg transition-all', activeView === 'reminders' ? 'bg-brand-accent text-white shadow-sm' : 'text-muted-ink hover:text-ink hover:bg-white/50')}
title={t('sidebar.reminders')}
>
<Clock size={14} />
</button>
<button
onClick={() => { setActiveView('agents'); router.push('/agents') }}
className={cn('flex-1 flex items-center justify-center py-1.5 rounded-lg transition-all', activeView === 'agents' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink hover:bg-white/50')}
className={cn('flex-1 flex items-center justify-center py-1.5 rounded-lg transition-all', activeView === 'agents' ? 'bg-brand-accent text-white shadow-sm' : 'text-muted-ink hover:text-ink hover:bg-white/50')}
title={t('nav.agents')}
>
<Bot size={14} />
</button>
<button
onClick={() => { setActiveView('brainstorms'); router.push('/brainstorm') }}
className={cn('flex-1 flex items-center justify-center py-1.5 rounded-lg transition-all', activeView === 'brainstorms' ? 'bg-ink text-paper shadow-sm' : 'text-muted-ink hover:text-ink hover:bg-white/50')}
className={cn('flex-1 flex items-center justify-center py-1.5 rounded-lg transition-all', activeView === 'brainstorms' ? 'bg-brand-accent text-white shadow-sm' : 'text-muted-ink hover:text-ink hover:bg-white/50')}
title={t('brainstorm.sessions')}
>
<Sparkles size={14} />
@@ -989,8 +989,8 @@ export function Sidebar({ className, user }: { className?: string; user?: any })
<div className={cn(
'w-8 h-8 rounded-full flex items-center justify-center text-sm font-medium border shrink-0',
isInboxActive
? 'bg-ink text-paper border-ink'
: 'bg-white/60 dark:bg-white/5 text-ink dark:text-foreground border-border'
? 'bg-brand-accent text-white border-brand-accent'
: 'bg-paper dark:bg-white/5 text-muted-ink border-border group-hover:border-brand-accent/20'
)}>
<Inbox size={14} />
</div>
@@ -1067,8 +1067,8 @@ export function Sidebar({ className, user }: { className?: string; user?: any })
<div className={cn(
'w-8 h-8 rounded-full flex items-center justify-center border transition-colors shrink-0',
isActive
? 'bg-foreground text-background border-foreground'
: 'bg-paper border-border group-hover:border-foreground/20'
? 'bg-brand-accent text-white border-brand-accent'
: 'bg-paper border-border group-hover:border-brand-accent/20'
)}>
<item.icon size={16} />
</div>
@@ -1109,15 +1109,15 @@ export function Sidebar({ className, user }: { className?: string; user?: any })
<UsageMeter />
<div className="px-2 space-y-0.5">
<Link
href="/?shared=1&forceList=1"
href="/home?shared=1&forceList=1"
className={cn(
'w-full flex items-center gap-3 px-3 py-2 text-[12px] transition-all font-medium group rounded-xl',
searchParams.get('shared') === '1' && pathname === '/'
searchParams.get('shared') === '1' && pathname === '/home'
? 'bg-accent/5 text-accent'
: 'text-muted-ink hover:text-ink hover:bg-black/5'
)}
>
<Users size={14} className={searchParams.get('shared') === '1' && pathname === '/' ? 'text-accent' : 'text-muted-ink group-hover:text-ink'} />
<Users size={14} className={searchParams.get('shared') === '1' && pathname === '/home' ? 'text-accent' : 'text-muted-ink group-hover:text-ink'} />
<span>{t('sidebar.sharedWithMe') || 'Shared'}</span>
</Link>

View File

@@ -1,10 +1,11 @@
'use client';
import { useState } from 'react';
import { useQuery } from '@tanstack/react-query';
import { useState, useEffect } from 'react';
import { useQuery, useQueryClient } from '@tanstack/react-query';
import { useRouter } from 'next/navigation';
import { cn } from '@/lib/utils';
import { Sparkles, X, Crown } from 'lucide-react';
import { Sparkles, ChevronDown, X, Crown } from 'lucide-react';
import { motion, AnimatePresence } from 'motion/react';
import { useLanguage } from '@/lib/i18n';
interface QuotaData {
@@ -17,27 +18,31 @@ interface UsageMeterProps {
className?: string;
}
function formatRemaining(value: number): string {
if (!Number.isFinite(value)) return '∞';
return String(value);
}
export function UsageMeter({ className }: UsageMeterProps) {
const { t } = useLanguage();
const router = useRouter();
const queryClient = useQueryClient();
const [expanded, setExpanded] = useState(false);
const [showModal, setShowModal] = useState(false);
const { data, isLoading } = useQuery({
queryKey: ['usage', 'current'],
queryFn: async () => {
const res = await fetch('/api/usage/current');
if (!res.ok) throw new Error('Failed to fetch quotas');
const data = await res.json();
return data.quotas as Record<string, QuotaData>;
const json = await res.json();
return { quotas: json.quotas as Record<string, QuotaData>, tier: json.tier as string };
},
refetchInterval: 30000,
staleTime: 5000,
refetchInterval: 10000,
});
if (isLoading || !data) {
useEffect(() => {
const handler = () => queryClient.invalidateQueries({ queryKey: ['usage', 'current'] });
window.addEventListener('ai-usage-changed', handler);
return () => window.removeEventListener('ai-usage-changed', handler);
}, [queryClient]);
if (isLoading || !data || !data.quotas) {
return (
<div className={cn('px-2 py-2', className)}>
<div className="h-8 rounded-lg bg-paper/50 animate-pulse" />
@@ -45,97 +50,151 @@ export function UsageMeter({ className }: UsageMeterProps) {
);
}
const features = [
{ key: 'semantic_search', labelKey: 'usageMeter.featureSearch' as const },
{ key: 'auto_tag', labelKey: 'usageMeter.featureTags' as const },
{ key: 'auto_title', labelKey: 'usageMeter.featureTitles' as const },
] as const;
const isProPlus = data.tier && data.tier !== 'BASIC';
const featureQuotas = features.map((f) => {
const quota = data[f.key];
return {
...f,
label: t(f.labelKey),
used: quota?.used ?? 0,
limit: quota?.limit ?? 0,
remaining: quota?.remaining ?? 0,
};
});
const featureLabels: Record<string, string> = {
semantic_search: t('usageMeter.featureSearch'),
auto_tag: t('usageMeter.featureTags'),
auto_title: t('usageMeter.featureTitles'),
reformulate: t('usageMeter.featureReformulate'),
chat: t('usageMeter.featureChat'),
brainstorm_create: t('usageMeter.featureBrainstormCreate'),
brainstorm_expand: t('usageMeter.featureBrainstormExpand'),
brainstorm_enrich: t('usageMeter.featureBrainstormEnrich'),
};
const featureQuotas = Object.entries(data.quotas)
.filter(([_, q]) => q.limit > 0)
.map(([key, quota]) => ({
key,
label: featureLabels[key] || key,
used: quota.used,
limit: quota.limit,
remaining: quota.remaining,
}));
const isUnlimited = featureQuotas.every((f) => !Number.isFinite(f.limit));
const totalRemaining = featureQuotas.reduce(
(sum, f) => sum + (Number.isFinite(f.remaining) ? f.remaining : 0),
0,
const totalUsed = featureQuotas.reduce(
(sum, f) => sum + (Number.isFinite(f.used) ? f.used : 0), 0,
);
const totalLimit = featureQuotas.reduce(
(sum, f) => sum + (Number.isFinite(f.limit) ? f.limit : 0),
0,
(sum, f) => sum + (Number.isFinite(f.limit) ? f.limit : 0), 0,
);
const used = totalLimit - totalRemaining;
const percentage = totalLimit > 0 ? Math.min((used / totalLimit) * 100, 100) : 0;
const totalRemaining = totalLimit - totalUsed;
const totalPct = totalLimit > 0 ? (totalUsed / totalLimit) * 100 : 0;
const isExhausted = !isUnlimited && totalRemaining <= 0;
const isLow = !isUnlimited && percentage >= 75 && !isExhausted;
return (
<>
<div className="px-2 py-2 w-full">
<div className="p-4 bg-slate-50 dark:bg-white/5 border border-border rounded-2xl space-y-3 group hover:shadow-lg transition-all duration-300">
<div className="flex items-center justify-between">
<div className="flex items-center gap-2">
<Sparkles
size={12}
className={
isExhausted
? 'text-rose-400 fill-rose-400/20'
: isUnlimited
? 'text-emerald-400 fill-emerald-400/20'
: 'text-brand-accent fill-brand-accent/20'
}
/>
<span className="text-[11px] font-bold text-ink/70">{t('usageMeter.packName')}</span>
</div>
<span
className={cn(
'text-[10px] font-medium',
isExhausted
? 'text-rose-500'
: isUnlimited
? 'text-emerald-500'
: isLow
? 'text-amber-500'
: 'text-concrete',
)}
>
{isUnlimited
? t('usageMeter.unlimited')
: t('usageMeter.remaining', { count: totalRemaining })}
</span>
</div>
{!isUnlimited && (
<div className="h-1.5 w-full bg-slate-200 dark:bg-white/10 rounded-full overflow-hidden">
<div
className={cn(
'h-full rounded-full transition-all duration-300',
isExhausted
? 'bg-rose-400'
: isLow
? 'bg-amber-400'
: 'bg-brand-accent',
)}
style={{ width: `${percentage}%` }}
/>
</div>
)}
<div className="bg-slate-50 dark:bg-white/5 border border-border rounded-2xl overflow-hidden">
<button
onClick={() => router.push('/settings/billing')}
className="w-full py-2 bg-brand-accent/10 hover:bg-brand-accent text-brand-accent hover:text-white text-[9px] font-bold uppercase tracking-widest rounded-xl transition-all duration-300 border border-brand-accent/20"
type="button"
onClick={() => setExpanded(!expanded)}
className="w-full p-3 flex items-center gap-2 hover:bg-slate-100 dark:hover:bg-white/5 transition-colors"
>
{t('usageMeter.upgradePricing') || 'Passer à Pro'}
<Sparkles
size={12}
className={cn(
'shrink-0',
isExhausted
? 'text-rose-400 fill-rose-400/20'
: isUnlimited
? 'text-emerald-400 fill-emerald-400/20'
: 'text-brand-accent fill-brand-accent/20'
)}
/>
<span className="text-[11px] font-bold text-ink/70">{t('usageMeter.packName')}</span>
{!isUnlimited && (
<>
<div className="flex-1 h-1 bg-slate-200 dark:bg-white/10 rounded-full overflow-hidden mx-2">
<div
className={cn(
'h-full rounded-full',
totalPct >= 90 ? 'bg-rose-400' : totalPct >= 70 ? 'bg-amber-400' : 'bg-brand-accent',
)}
style={{ width: `${Math.min(totalPct, 100)}%` }}
/>
</div>
<span className={cn(
'text-[10px] font-medium tabular-nums shrink-0',
totalPct >= 90 ? 'text-rose-500' : totalPct >= 70 ? 'text-amber-500' : 'text-concrete'
)}>
{totalRemaining}
</span>
</>
)}
{isUnlimited && (
<span className="text-[10px] font-medium text-emerald-500 ml-auto">{t('usageMeter.unlimited')}</span>
)}
{isProPlus && !isUnlimited && (
<span className="text-[9px] font-bold text-brand-accent uppercase tracking-widest ml-auto">{data.tier}</span>
)}
<ChevronDown
size={12}
className={cn(
'text-concrete shrink-0 transition-transform duration-200',
expanded && 'rotate-180',
)}
/>
</button>
<AnimatePresence initial={false}>
{expanded && (
<motion.div
initial={{ height: 0, opacity: 0 }}
animate={{ height: 'auto', opacity: 1 }}
exit={{ height: 0, opacity: 0 }}
transition={{ duration: 0.2, ease: 'easeInOut' }}
className="overflow-hidden"
>
<div className="px-3 pb-3 space-y-2">
<div className="border-t border-border/40 pt-2" />
{featureQuotas.map((f) => {
const fPct = Number.isFinite(f.limit) && f.limit > 0 ? (f.used / f.limit) * 100 : 0
return (
<div key={f.key} className="space-y-1">
<div className="flex justify-between text-[10px]">
<span className="text-concrete truncate">{f.label}</span>
<span className={cn(
'font-medium tabular-nums',
fPct >= 90 ? 'text-rose-500' : fPct >= 70 ? 'text-amber-500' : 'text-ink/60'
)}>
{!Number.isFinite(f.remaining) ? '∞' : f.remaining}/{!Number.isFinite(f.limit) ? '∞' : f.limit}
</span>
</div>
{Number.isFinite(f.limit) && (
<div className="h-1 w-full bg-slate-200 dark:bg-white/10 rounded-full overflow-hidden">
<div
className={cn(
'h-full rounded-full transition-all duration-300',
fPct >= 90 ? 'bg-rose-400' : fPct >= 70 ? 'bg-amber-400' : 'bg-brand-accent',
)}
style={{ width: `${Math.min(fPct, 100)}%` }}
/>
</div>
)}
</div>
)
})}
{!isProPlus && (
<button
onClick={(e) => { e.stopPropagation(); router.push('/settings/billing'); }}
className="w-full mt-2 py-2 bg-brand-accent/10 hover:bg-brand-accent text-brand-accent hover:text-white text-[9px] font-bold uppercase tracking-widest rounded-xl transition-all duration-300 border border-brand-accent/20"
>
{t('usageMeter.upgradePricing') || 'Passer à Pro'}
</button>
)}
</div>
</motion.div>
)}
</AnimatePresence>
</div>
</div>

Binary file not shown.

After

Width:  |  Height:  |  Size: 165 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 186 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 131 KiB

View File

@@ -32,7 +32,11 @@ export function useBrainstormSocket(
const [activities, setActivities] = useState<ActivityEvent[]>([])
const [aiProcessingNodeId, setAiProcessingNodeId] = useState<string | null>(null)
const effectiveUserId = userId || `guest_${Math.random().toString(36).slice(2, 10)}`
const guestIdRef = useRef<string | null>(null)
if (!guestIdRef.current && !userId) {
guestIdRef.current = `guest_${Math.random().toString(36).slice(2, 10)}`
}
const effectiveUserId = userId || guestIdRef.current!
useEffect(() => {
if (!sessionId) return
@@ -85,8 +89,6 @@ export function useBrainstormSocket(
return () => {
socket.disconnect()
socketRef.current = null
setOthers([])
setAiProcessingNodeId(null)
}
}, [sessionId, effectiveUserId, userName])

View File

@@ -15,16 +15,24 @@ export interface EmbeddingResult {
export class EmbeddingService {
private readonly EMBEDDING_DIMENSION = 1536
private readonly MAX_CHARS = 15000
private truncateForEmbedding(text: string): string {
if (text.length <= this.MAX_CHARS) return text
return text.slice(0, this.MAX_CHARS)
}
async generateEmbedding(text: string): Promise<EmbeddingResult> {
if (!text || text.trim().length === 0) {
throw new Error('Cannot generate embedding for empty text')
}
const truncated = this.truncateForEmbedding(text)
try {
const config = await getSystemConfig()
const embedding = await withAiProviderFallback('embedding', config, (provider) =>
provider.getEmbeddings(text)
provider.getEmbeddings(truncated)
)
return {
@@ -41,7 +49,7 @@ export class EmbeddingService {
async generateBatchEmbeddings(texts: string[]): Promise<EmbeddingResult[]> {
if (!texts || texts.length === 0) return []
const validTexts = texts.filter(t => t && t.trim().length > 0)
const validTexts = texts.filter(t => t && t.trim().length > 0).map(t => this.truncateForEmbedding(t))
if (validTexts.length === 0) return []
try {

View File

@@ -77,14 +77,14 @@ export class MemoryEchoService {
for (const note of notesWithoutEmbeddings) {
if (!note.content || note.content.trim().length === 0) continue
try {
const embedding = await provider.getEmbeddings(note.content)
const embedding = await provider.getEmbeddings(note.content.slice(0, 15000))
if (embedding && embedding.length > 0) {
const vecStr = `[${embedding.join(',')}]`
await prisma.$executeRawUnsafe(
`INSERT INTO "NoteEmbedding" ("id", "noteId", "embedding", "createdAt", "updatedAt")
VALUES (gen_random_uuid(), $1, $2::vector, now(), now())
`INSERT INTO "NoteEmbedding" ("id", "noteId", "embedding", "createdAt")
VALUES (gen_random_uuid(), $1, $2::vector, now())
ON CONFLICT ("noteId")
DO UPDATE SET "embedding" = $2::vector, "updatedAt" = now()`,
DO UPDATE SET "embedding" = $2::vector`,
note.id,
vecStr
)

View File

@@ -286,11 +286,15 @@ Only return the translated text, nothing else.`,
Keep the explanation clear, educational, and concise.`
}
const systemSuffix = mode === 'explain'
? `CRITICAL: Respond ONLY with your explanation in ${language}. No meta-commentary, no English. Format strictly as ${format === 'html' ? 'HTML tags' : 'Markdown'}.`
: `CRITICAL: Respond ONLY with the refactored text in ${language}. No explanations, no meta-commentary, no English. Format strictly as ${format === 'html' ? 'HTML tags' : 'Markdown'}.`
return `${instructions[mode]}
${content}
CRITICAL: Respond ONLY with the refactored text in ${language}. No explanations, no meta-commentary, no English. Format strictly as ${format === 'html' ? 'HTML tags' : 'Markdown'}.`
${systemSuffix}`
}
/**

View File

@@ -235,15 +235,15 @@ export class SemanticSearchService {
const rows: Array<{ noteId: string; similarity: number }> = await prisma.$queryRawUnsafe(
`SELECT n.id AS "noteId",
1 - (e."embedding" <=> ${vecParam}) AS similarity
1 - (e."embedding"::vector <=> ${vecParam}) AS similarity
FROM "Note" n
INNER JOIN "NoteEmbedding" e ON e."noteId" = n.id
WHERE n."trashedAt" IS NULL
AND n."isArchived" = false
${userClause}
${notebookClause}
AND 1 - (e."embedding" <=> ${vecParam}) >= ${thresholdParam}
ORDER BY e."embedding" <=> ${vecParam} ASC
AND 1 - (e."embedding"::vector <=> ${vecParam}) >= ${thresholdParam}
ORDER BY e."embedding"::vector <=> ${vecParam} ASC
LIMIT ${limitParam}`,
...params
)
@@ -356,10 +356,10 @@ export class SemanticSearchService {
const vecStr = embeddingService.toVectorString(embedding)
await prisma.$queryRawUnsafe(
`INSERT INTO "NoteEmbedding" ("id", "noteId", "embedding", "createdAt", "updatedAt")
VALUES (gen_random_uuid(), $1, $2::vector, now(), now())
`INSERT INTO "NoteEmbedding" ("id", "noteId", "embedding", "createdAt")
VALUES (gen_random_uuid(), $1, $2::vector, now())
ON CONFLICT ("noteId")
DO UPDATE SET "embedding" = $2::vector, "updatedAt" = now()`,
DO UPDATE SET "embedding" = $2::vector`,
noteId,
vecStr
)
@@ -427,7 +427,7 @@ export class SemanticSearchService {
AND n."trashedAt" IS NULL
AND n."userId" = $3
${noteFilter}
ORDER BY dc."embedding" <=> $1::vector
ORDER BY dc."embedding"::vector <=> $1::vector
LIMIT $2`,
...params
) as any[]

View File

@@ -31,6 +31,7 @@ export class QuotaExceededError extends Error {
billingOwnerId?: string;
triggeredByUserId?: string;
isGuestActor?: boolean;
currentTier?: string;
constructor(
upgradeTier: 'PRO' | 'BUSINESS',
@@ -42,6 +43,7 @@ export class QuotaExceededError extends Error {
billingOwnerId?: string;
triggeredByUserId?: string;
isGuestActor?: boolean;
currentTier?: string;
},
) {
super(`Quota exceeded for ${feature}`);
@@ -53,6 +55,7 @@ export class QuotaExceededError extends Error {
this.billingOwnerId = sessionMeta?.billingOwnerId;
this.triggeredByUserId = sessionMeta?.triggeredByUserId;
this.isGuestActor = sessionMeta?.isGuestActor;
this.currentTier = sessionMeta?.currentTier;
}
toJSON() {
@@ -62,6 +65,7 @@ export class QuotaExceededError extends Error {
upgradeTier: this.upgradeTier,
byokConfigured: this.byokConfigured,
isGuestActor: this.isGuestActor ?? false,
currentTier: this.currentTier,
};
}
}
@@ -121,6 +125,18 @@ local newCount = tonumber(redis.call('GET', KEYS[1]))
return newCount
`;
const INCREMENT_BY_LUA = `
local count = tonumber(ARGV[1]) or 1
local ttl = tonumber(ARGV[2])
redis.call('INCRBY', KEYS[1], count)
local ttlResult = redis.call('TTL', KEYS[1])
if ttlResult == -1 then
redis.call('EXPIRE', KEYS[1], ttl)
end
local newCount = tonumber(redis.call('GET', KEYS[1]))
return newCount
`;
const RESERVE_LUA = `
local limit = tonumber(ARGV[1])
local ttl = tonumber(ARGV[2])
@@ -252,6 +268,7 @@ export async function checkEntitlementOrThrow(
result.limit,
result.limit > 0 ? result.limit - result.remaining : 0,
result.byokConfigured ?? false,
{ currentTier: result.tier },
);
}
}
@@ -261,7 +278,7 @@ export async function reserveUsageOrThrow(
feature: string,
): Promise<void> {
if (!isValidFeature(feature)) {
throw new QuotaExceededError('PRO', feature, 0, 0, false);
throw new QuotaExceededError('PRO', feature, 0, 0, false, { currentTier: 'BASIC' });
}
const tier = await getEffectiveTier(userId);
@@ -274,6 +291,7 @@ export async function reserveUsageOrThrow(
0,
0,
false,
{ currentTier: tier },
);
}
@@ -297,6 +315,7 @@ export async function reserveUsageOrThrow(
limit,
limit,
byokConfigured,
{ currentTier: tier },
);
}
} catch (err) {
@@ -324,11 +343,11 @@ export async function checkSessionEntitlementOrThrow(
}
}
export function incrementUsageAsync(userId: string, feature: string): Promise<void> {
export function incrementUsageAsync(userId: string, feature: string, count: number = 1): Promise<void> {
if (!isValidFeature(feature)) return Promise.resolve();
const key = getRedisKey(userId, feature);
return redis.eval(INCREMENT_LUA, 1, key, String(TTL_SECONDS)).then(() => {}).catch((err) => {
return redis.eval(INCREMENT_BY_LUA, 1, key, String(count), String(TTL_SECONDS)).then(() => {}).catch((err) => {
console.error('[entitlements] Async increment failed:', err);
});
}

View File

@@ -890,7 +890,7 @@
"recentNotesUpdateFailed": "فشل تحديث إعدادات الملاحظات الحديثة"
},
"aiSettings": {
"title": "إعدادات الذكاء الاصطناعي",
"title": "AI",
"description": "تكوين ميزاتك وتفضيلاتك المدعومة بالذكاء الاصطناعي",
"features": "ميزات الذكاء الاصطناعي",
"provider": "مزود الذكاء الاصطناعي",
@@ -917,7 +917,8 @@
"autoLabeling": "اقتراحات التسميات",
"autoLabelingDesc": "يقترح ويطبق التسميات تلقائياً على ملاحظاتك",
"noteHistory": "سجل الملاحظة",
"noteHistoryDesc": "تفعيل لقطات النسخ والاستعادة من السجل"
"noteHistoryDesc": "تفعيل لقطات النسخ والاستعادة من السجل",
"titleSuggestions": "اقتراحات العناوين"
},
"general": {
"loading": "جاري التحميل...",
@@ -1115,7 +1116,13 @@
"languageDetection": "اكتشاف اللغة",
"languageDetectionDesc": "يكتشف تلقائياً لغة كل ملاحظة",
"autoLabeling": "التصنيف التلقائي",
"autoLabelingDesc": "يقترح ويطبق التصنيفات تلقائياً"
"autoLabelingDesc": "يقترح ويطبق التصنيفات تلقائياً",
"fallbackSectionTitle": "مزود احتياطي (اختياري)",
"fallbackSectionDescription": "يُستخدم تلقائياً عند أخطاء المزود (429، 5xx). محاولة واحدة خلال 1,5 ثانية.",
"fallbackProvider": "مزود احتياطي",
"fallbackModel": "نموذج احتياطي",
"fallbackNone": "لا شيء (معطّل)",
"fallbackModelPlaceholder": "مثال: gpt-4o-mini"
},
"resend": {
"title": "Resend (موصى به)",
@@ -1173,6 +1180,8 @@
"deleteFailed": "فشل الحذف",
"roleUpdateSuccess": "تم تحديث دور المستخدم إلى {role}",
"roleUpdateFailed": "فشل تحديث الدور",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "تخفيض إلى مستخدم",
"promote": "ترقية إلى مشرف",
"confirmDelete": "هل أنت متأكد؟ لا يمكن التراجع عن هذا الإجراء.",
@@ -1180,6 +1189,7 @@
"name": "الاسم",
"email": "البريد الإلكتروني",
"role": "الدور",
"subscription": "Subscription",
"createdAt": "تاريخ الإنشاء",
"actions": "الإجراءات"
},
@@ -1371,7 +1381,7 @@
"loading": "جاري التحميل..."
},
"dataManagement": {
"title": "إدارة البيانات",
"title": "Data",
"toolsDescription": "أدوات للحفاظ على صحة قاعدة البيانات",
"exporting": "جاري التصدير...",
"importing": "جاري الاستيراد...",
@@ -1436,7 +1446,7 @@
"fontJetBrainsMono": "JetBrains Mono"
},
"generalSettings": {
"title": "الإعدادات العامة",
"title": "General",
"description": "إعدادات التطبيق العامة"
},
"toast": {
@@ -1622,7 +1632,7 @@
"collapse": "طي"
},
"mcpSettings": {
"title": "إعدادات MCP",
"title": "MCP",
"description": "إدارة مفاتيح API وتكوين الأدوات الخارجية",
"whatIsMcp": {
"title": "ما هو MCP؟",
@@ -2211,7 +2221,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "استنفد مضيف الجلسة حدّ الذكاء الاصطناعي. اطلب منه ترقية خطته.",
"quotaHost": "لقد وصلت إلى حدّ الذكاء الاصطناعي لهذه الجلسة. رقِّ خطتك للمتابعة."
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2323,6 +2335,215 @@
"checkoutSuccessBody": "مرحبًا في {tier}. ميزاتك متاحة الآن.",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"currentUsage": "الاستخدام الحالي",
"currentPeriod": "الفترة الحالية",
"aiCredits": "أرصدة الذكاء الاصطناعي",
"used": "مستخدم",
"billing": "الفواتير",
"renewal": "التجديد",
"paidPlanDesc": "يتم تجديد اشتراكك تلقائيًا.",
"businessDescription": "للفرق وقادة المنتجات."
},
"landing": {
"nav": {
"features": "الميزات",
"agents": "وكلاء الذكاء الاصطناعي",
"brainstorm": "العصف الذهني",
"pricing": "الأسعار",
"tech": "البنية",
"login": "تسجيل الدخول",
"cta": "ابدأ الآن"
},
"hero": {
"badge": "مدعوم بالذكاء الاصطناعي",
"title1": "عقلك الثاني،",
"title2": "مُعزَّز أخيرًا.",
"subtitle": "Momento ليست مجرد تطبيق للملاحظات. إنها منظومة ذكية تربط أفكارك وتحللها وتطورها في الوقت الفعلي بفضل 6 أنواع من وكلاء الذكاء الاصطناعي والبحث الدلالي المتقدم.",
"cta": "سجّل الآن",
"secondary": "استكشف الميزات",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"تم رصد ارتباط بمشروع التصميم المستدام الخاص بك من مارس 2024...\"",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12 فكرة مُولَّدة"
},
"features": {
"label": "قدرات الذكاء الاصطناعي",
"title": "ذكاء سلس،",
"title2": "منسوج في كل كلمة.",
"desc": "تنسّق Momento أفكارك عبر بنية متعددة المزوّدين.",
"f1Title": "البحث الدلالي",
"f1Desc": "توقّف عن البحث بالكلمات المفتاحية. ابحث بالمفهوم. محركنا الهجين Vector + FTS يفهم القصد وراء ملاحظاتك.",
"f2Title": "دردشة RAG السياقية",
"f2Desc": "تحدّث مع معرفتك. يقرأ وكلاؤنا ملاحظاتك ويستكشفون الويب ويحللون مستنداتك للإجابة بدقة.",
"f3Title": "كتابة معزّزة",
"f3Desc": "إعادة الصياغة واقتراح العناوين والوسم التلقائي والملخصات. يعمل الذكاء الاصطناعي في الخلفية لتنظيم تفكيرك."
},
"agents": {
"label": "وكلاء متخصصون",
"title": "فوّض العمل المعقّد.",
"desc": "6 أنواع من وكلاء الذكاء الاصطناعي المستقلين لأتمتة أبحاثك وملخصاتك وعروضك.",
"scraper": {
"title": "Scraper",
"desc": "يجمع الروابط ويحلل خلاصات RSS ويلخّص المعلومات مع وضع ذكي للصور."
},
"researcher": {
"title": "Researcher",
"desc": "يولّد استعلامات معقدة ويستكشف مصادر الويب ويكتب ملاحظات بحث منظمة."
},
"slideGen": {
"title": "Slide Gen",
"desc": "يحوّل ملاحظاتك إلى عروض PowerPoint احترافية أو شرائح HTML تفاعلية."
},
"monitor": {
"title": "Monitor",
"desc": "يحلل دفاترك باستمرار لاكتشاف الاتجاهات والرؤى الجديدة."
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "يحوّل أفكارك إلى مخططات Excalidraw سلسة (خرائط ذهنية، مخططات انسيابية) بتخطيط تلقائي."
},
"custom": {
"title": "Custom",
"desc": "عرّف وكلاءك بأدوار ومصادر بيانات مخصّصة."
}
},
"brainstorm": {
"label": "موجات الفكر",
"title": "عصف ذهني شعاعي في الوقت الفعلي.",
"waveGeneration": {
"title": "توليد بالموجات",
"desc": "تنويعات وتشبيهات ثم اختراقات. يدفع الذكاء الاصطناعي مفهومك الأولي إلى أقصى حدوده."
},
"collaboration": {
"title": "تعاون أصيل",
"desc": "مؤشرات شبحية للذكاء الاصطناعي وأفاتار متزامنة وتحريك العقد في الوقت الفعلي."
},
"export": {
"title": "تصدير دلالي",
"desc": "حوّل جلسة العصف الذهني بالكامل إلى ملاحظات منظمة بنقرة واحدة."
},
"disruptionLabel": "اختراق",
"disruptionText": "بنية معيارية 2.0",
"analogyLabel": "تشبيه",
"analogyText": "دورة المد والجزر"
},
"tech": {
"label": "البنية والمزوّدون",
"title": "اربط نموذج الذكاء الاصطناعي الخاص بك.",
"tags": {
"title": "الوسوم",
"desc": "قابل للإعداد بشكل مستقل مع أي نموذج."
},
"embeddings": {
"title": "Embeddings",
"desc": "قابل للإعداد بشكل مستقل مع أي نموذج."
},
"chatRag": {
"title": "Chat RAG",
"desc": "قابل للإعداد بشكل مستقل مع أي نموذج."
}
},
"pricing": {
"label": "الخطط والأسعار",
"title": "اختر مستوى التعزيز المناسب لك.",
"desc": "خيارات مرنة للعقول المبدعة، من الاستخدام الفردي إلى المؤسسات الكبيرة.",
"monthly": "شهري",
"annual": "سنوي",
"perMonth": "/شهر",
"perMonthAnnual": "/شهر، يُفوتر سنويًا",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "الأكثر شعبية",
"basic": {
"name": "Basic",
"desc": "اكتشف سحر Momento.",
"cta": "ابدأ",
"feature0": "100 ملاحظة كحد أقصى",
"feature1": "3 دفاتر",
"feature2": "50 رصيد ذكاء اصطناعي (مدى الحياة)",
"feature3": "بحث دلالي",
"feature4": "سجل 7 أيام"
},
"pro": {
"name": "Pro",
"desc": "للمستشارين والمبدعين الطموحين.",
"cta": "الترقية إلى Pro",
"feature0": "ملاحظات غير محدودة",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "200 بحث دلالي",
"feature3": "الوكلاء (12 تشغيل/شهر)",
"feature4": "سجل 30 يومًا",
"feature5": "دعم عبر البريد"
},
"business": {
"name": "Business",
"desc": "للفرق ومديري المنتجات.",
"cta": "اختر Business",
"feature0": "10 متعاونين مشمولين",
"feature1": "BYOK (13 مزوّدًا)",
"feature2": "1000 بحث دلالي",
"feature3": "الوكلاء (60 تشغيل/شهر)",
"feature4": "عصف ذهني غير محدود",
"feature5": "وصول API"
},
"enterprise": {
"name": "Enterprise",
"desc": "ذاكرة مؤسسية آمنة.",
"cta": "تواصل مع المبيعات",
"feature0": "كل ما في Business",
"feature1": "وكلاء غير محدودين",
"feature2": "SSO / SAML",
"feature3": "سجلات تدقيق وSLA",
"feature4": "دعم مخصص",
"feature5": "إعداد مباشر"
}
},
"byok": {
"label": "تقنية سحابية مفتوحة",
"title": "استراتيجية BYOK",
"desc": "لديك مفاتيح API من OpenAI أو Anthropic أو Google؟ اربطها مباشرة بـ Momento. استخدم الذكاء الاصطناعي دون حدود ائتمان مفروضة، وادفع فقط ما تستهلكه لدى مزوّدك المفضل.",
"noLockin": "بدون قفل",
"noLockinDesc": "بدّل المزوّد بنقرة واحدة.",
"cost": "تكاليف محسّنة",
"costDesc": "ادفع سعر API المباشر.",
"configLabel": "إعداد متعدد المزوّدين"
},
"cta": {
"title1": "مستعد لإطلاق",
"title2": "إمكاناتك الكاملة؟",
"desc": "انضم إلى آلاف الباحثين والمصممين والمفكرين الذين يستخدمون Momento لبناء مستقبلهم.",
"button": "تشغيل Momento"
},
"footer": {
"desc": "العقل الثاني المعزّز بالذكاء الاصطناعي. صُمم للعقول المبدعة.",
"product": {
"title": "المنتج",
"link0": "سجل التغييرات",
"link1": "التوثيق",
"link2": "خارطة الطريق",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "المجتمع",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "قانوني",
"link0": "سياسة الخصوصية",
"link1": "شروط الخدمة",
"link2": "سياسة ملفات تعريف الارتباط",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -890,7 +890,7 @@
"recentNotesUpdateFailed": "Failed to update recent notes setting"
},
"aiSettings": {
"title": "KI-Einstellungen",
"title": "AI",
"description": "Konfigurieren Sie Ihre KI-gesteuerten Funktionen und Präferenzen",
"features": "KI-Funktionen",
"provider": "KI-Anbieter",
@@ -917,7 +917,8 @@
"autoLabeling": "Etikettenvorschläge",
"autoLabelingDesc": "Schlagt automatisch Beschriftungen für Ihre Notizen vor und wendet diese an",
"noteHistory": "Notizverlauf",
"noteHistoryDesc": "Aktivieren Sie Versions-Snapshots und die Wiederherstellung aus dem Verlauf"
"noteHistoryDesc": "Aktivieren Sie Versions-Snapshots und die Wiederherstellung aus dem Verlauf",
"titleSuggestions": "Titelvorschläge"
},
"general": {
"loading": "Wird geladen...",
@@ -1115,7 +1116,13 @@
"languageDetection": "Spracherkennung",
"languageDetectionDesc": "Erkennt automatisch die Sprache jeder Notiz",
"autoLabeling": "Automatische Beschriftung",
"autoLabelingDesc": "Schlägt Labels vor und wendet sie automatisch an"
"autoLabelingDesc": "Schlägt Labels vor und wendet sie automatisch an",
"fallbackSectionTitle": "Ausweich-Anbieter (optional)",
"fallbackSectionDescription": "Wird bei Anbieterfehlern automatisch genutzt (429, 5xx). Ein erneuter Versuch innerhalb von 1,5 s.",
"fallbackProvider": "Ausweich-Anbieter",
"fallbackModel": "Ausweich-Modell",
"fallbackNone": "Keiner (deaktiviert)",
"fallbackModelPlaceholder": "z. B. gpt-4o-mini"
},
"resend": {
"title": "Resend (Empfohlen)",
@@ -1173,6 +1180,8 @@
"deleteFailed": "Fehler beim Löschen",
"roleUpdateSuccess": "Benutzerrolle zu {role} aktualisiert",
"roleUpdateFailed": "Fehler beim Aktualisieren der Rolle",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "Zurückstufen",
"promote": "Befördern",
"confirmDelete": "Möchten Sie diesen Benutzer wirklich löschen?",
@@ -1180,6 +1189,7 @@
"name": "Name",
"email": "E-Mail",
"role": "Rolle",
"subscription": "Subscription",
"createdAt": "Erstellt am",
"actions": "Aktionen"
},
@@ -1371,7 +1381,7 @@
"loading": "Wird geladen..."
},
"dataManagement": {
"title": "Datenverwaltung",
"title": "Data",
"toolsDescription": "Werkzeuge zur Pflege Ihrer Datenbankgesundheit",
"exporting": "Wird exportiert...",
"importing": "Wird importiert...",
@@ -1436,7 +1446,7 @@
"fontJetBrainsMono": "JetBrains Mono"
},
"generalSettings": {
"title": "Allgemeine Einstellungen",
"title": "General",
"description": "Allgemeine Anwendungseinstellungen"
},
"toast": {
@@ -1622,7 +1632,7 @@
"collapse": "Zusammenklappen"
},
"mcpSettings": {
"title": "MCP-Einstellungen",
"title": "MCP",
"description": "API-Schlüssel verwalten und externe Tools konfigurieren",
"whatIsMcp": {
"title": "Was ist MCP?",
@@ -2211,7 +2221,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "Der Gastgeber der Sitzung hat sein KI-Kontingent aufgebraucht. Bitte ihn, seinen Tarif zu erweitern.",
"quotaHost": "Sie haben Ihr KI-Kontingent für dieses Brainstorming erreicht. Wechseln Sie den Tarif, um fortzufahren."
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2323,6 +2335,215 @@
"checkoutSuccessBody": "Willkommen bei {tier}. Ihre Funktionen sind jetzt freigeschaltet.",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"currentUsage": "Aktuelle Nutzung",
"currentPeriod": "Aktueller Zeitraum",
"aiCredits": "KI-Guthaben",
"used": "verwendet",
"billing": "Abrechnung",
"renewal": "Verlängerung",
"paidPlanDesc": "Ihr Abonnement verlängert sich automatisch.",
"businessDescription": "Für Teams und Produktverantwortliche."
},
"landing": {
"nav": {
"features": "Funktionen",
"agents": "KI-Agenten",
"brainstorm": "Brainstorm",
"pricing": "Preise",
"tech": "Architektur",
"login": "Anmelden",
"cta": "Jetzt starten"
},
"hero": {
"badge": "Angetrieben von Künstlicher Intelligenz",
"title1": "Ihr zweites Gehirn,",
"title2": "endlich verstärkt.",
"subtitle": "Momento ist mehr als eine Notizen-App. Es ist ein intelligentes Ökosystem, das Ihre Ideen in Echtzeit verbindet, analysiert und weiterentwickelt mit 6 Arten von KI-Agenten und modernster semantischer Suche.",
"cta": "Jetzt registrieren",
"secondary": "Funktionen ansehen",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"Verbindung erkannt mit Ihrem Nachhaltigkeitsdesign-Projekt von März 2024...\"",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12 Ideen generiert"
},
"features": {
"label": "KI-Fähigkeiten",
"title": "Fließende Intelligenz,",
"title2": "in jedes Wort eingewoben.",
"desc": "Momento orchestriert Ihre Ideen über eine Multi-Provider-Architektur.",
"f1Title": "Semantische Suche",
"f1Desc": "Schluss mit der Stichwortsuche. Finden Sie nach Konzept. Unsere hybride Vector- und FTS-Engine versteht die Absicht hinter Ihren Notizen.",
"f2Title": "Kontextueller RAG-Chat",
"f2Desc": "Sprechen Sie mit Ihrem Wissen. Unsere Agenten lesen Ihre Notizen, erkunden das Web und analysieren Ihre Dokumente für präzise Antworten.",
"f3Title": "Erweitertes Schreiben",
"f3Desc": "Umformulierung, Titelvorschläge, automatisches Tagging und Zusammenfassungen. Die KI strukturiert Ihr Denken im Hintergrund."
},
"agents": {
"label": "Spezialisierte Agenten",
"title": "Delegieren Sie die komplexe Arbeit.",
"desc": "6 Arten autonomer KI-Agenten für Recherche, Zusammenfassungen und Präsentationen.",
"scraper": {
"title": "Scraper",
"desc": "Erfasst URLs, parst RSS-Feeds und fasst Informationen mit intelligentem Bild-Layout zusammen."
},
"researcher": {
"title": "Researcher",
"desc": "Erstellt komplexe Abfragen, erkundet Webquellen und schreibt strukturierte Recherchenotizen."
},
"slideGen": {
"title": "Slide Gen",
"desc": "Verwandelt Ihre Notizen in professionelle PowerPoint-Präsentationen oder interaktive HTML-Slides."
},
"monitor": {
"title": "Monitor",
"desc": "Analysiert Ihre Notizbücher fortlaufend, um Trends und neue Erkenntnisse zu erkennen."
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "Wandelt Ideen in flüssige Excalidraw-Diagramme (Mindmaps, Flowcharts) mit Auto-Layout um."
},
"custom": {
"title": "Custom",
"desc": "Definieren Sie eigene Agenten mit spezifischen Rollen und Datenquellen."
}
},
"brainstorm": {
"label": "Gedankenwellen",
"title": "Radiales Brainstorming in Echtzeit.",
"waveGeneration": {
"title": "Wellengenerierung",
"desc": "Variationen, Analogien, dann Disruptionen. Die KI treibt Ihr Ausgangskonzept an seine Grenzen."
},
"collaboration": {
"title": "Native Zusammenarbeit",
"desc": "KI-Geistercursor, synchronisierte Avatare und Knotenbewegung in Echtzeit."
},
"export": {
"title": "Semantischer Export",
"desc": "Wandeln Sie Ihr gesamtes Brainstorming mit einem Klick in strukturierte Notizen um."
},
"disruptionLabel": "DISRUPTION",
"disruptionText": "Modulare Architektur 2.0",
"analogyLabel": "ANALOGIE",
"analogyText": "Der Gezeitenzyklus"
},
"tech": {
"label": "Architektur & Anbieter",
"title": "Verbinden Sie Ihr eigenes KI-Modell.",
"tags": {
"title": "Tags",
"desc": "Unabhängig mit jedem Modell konfigurierbar."
},
"embeddings": {
"title": "Embeddings",
"desc": "Unabhängig mit jedem Modell konfigurierbar."
},
"chatRag": {
"title": "Chat RAG",
"desc": "Unabhängig mit jedem Modell konfigurierbar."
}
},
"pricing": {
"label": "Pläne & Preise",
"title": "Wählen Sie Ihr Verstärkungsniveau.",
"desc": "Flexible Optionen für kreative Köpfe vom Einzelgebrauch bis zu großen Organisationen.",
"monthly": "Monatlich",
"annual": "Jährlich",
"perMonth": "/Monat",
"perMonthAnnual": "/Monat, jährlich abgerechnet",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "Am beliebtesten",
"basic": {
"name": "Basic",
"desc": "Entdecken Sie die Magie von Momento.",
"cta": "Loslegen",
"feature0": "Max. 100 Notizen",
"feature1": "3 Notizbücher",
"feature2": "50 KI-Credits (lebenslang)",
"feature3": "Semantische Suche",
"feature4": "7-Tage-Verlauf"
},
"pro": {
"name": "Pro",
"desc": "Für anspruchsvolle Berater und Kreative.",
"cta": "Auf Pro upgraden",
"feature0": "Unbegrenzte Notizen",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "200 semantische Suchen",
"feature3": "Agenten (12 Läufe/Monat)",
"feature4": "30-Tage-Verlauf",
"feature5": "E-Mail-Support"
},
"business": {
"name": "Business",
"desc": "Für Teams und Produktmanager.",
"cta": "Business wählen",
"feature0": "10 Mitarbeitende inklusive",
"feature1": "BYOK (13 Anbieter)",
"feature2": "1000 semantische Suchen",
"feature3": "Agenten (60 Läufe/Monat)",
"feature4": "Unbegrenztes Brainstorming",
"feature5": "API-Zugang"
},
"enterprise": {
"name": "Enterprise",
"desc": "Sicheres organisationales Gedächtnis.",
"cta": "Vertrieb kontaktieren",
"feature0": "Alles aus Business",
"feature1": "Unbegrenzte Agenten",
"feature2": "SSO / SAML",
"feature3": "Audit-Logs & SLA",
"feature4": "Dedizierter Support",
"feature5": "Live-Onboarding"
}
},
"byok": {
"label": "Offene Cloud-Technologie",
"title": "Die BYOK-Strategie",
"desc": "Sie haben bereits API-Schlüssel von OpenAI, Anthropic oder Google? Verbinden Sie sie direkt mit Momento. Nutzen Sie KI ohne erzwungene Credit-Limits und zahlen Sie nur, was Sie beim Anbieter Ihrer Wahl tatsächlich verbrauchen.",
"noLockin": "Kein Lock-in",
"noLockinDesc": "Anbieter mit einem Klick wechseln.",
"cost": "Optimierte Kosten",
"costDesc": "Zahlen Sie den direkten API-Preis.",
"configLabel": "Multi-Provider-Konfiguration"
},
"cta": {
"title1": "Bereit, Ihr",
"title2": "volles Potenzial freizusetzen?",
"desc": "Schließen Sie sich Tausenden von Forschern, Designern und Denkern an, die Momento bereits nutzen, um ihre Zukunft zu gestalten.",
"button": "Momento starten"
},
"footer": {
"desc": "Das KI-verstärkte zweite Gehirn. Für kreative Köpfe entwickelt.",
"product": {
"title": "Produkt",
"link0": "Changelog",
"link1": "Dokumentation",
"link2": "Roadmap",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "Community",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "Rechtliches",
"link0": "Datenschutz",
"link1": "Nutzungsbedingungen",
"link2": "Cookie-Richtlinie",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -394,7 +394,7 @@
"transformError": "Error during transformation",
"convertToRichtext": "Convert to Rich Text",
"convertingToRichtext": "Converting...",
"assistant": "AI Assistant",
"assistant": "AI Note",
"generating": "Generating...",
"generateTitles": "Generate titles",
"reformulateText": "Reformulate text",
@@ -457,8 +457,8 @@
"undoAI": "Undo AI transformation",
"undoApplied": "Original text restored",
"minWordsError": "Note must contain at least 5 words to use AI actions.",
"wordCountMin": "Please select at least {min} words to reformulate (currently {current} words)",
"wordCountMax": "Please select at most {max} words to reformulate (currently {current} words)",
"wordCountMin": "Minimum {min} words required ({current} current)",
"wordCountMax": "Maximum {max} words allowed ({current} current)",
"genericError": "AI error",
"actionError": "Error during AI action",
"appliedToNote": "Applied to note",
@@ -467,7 +467,7 @@
"selectContext": "Select context...",
"selectNotebook": "Select notebook",
"chatPlaceholder": "Ask AI to edit, summarize, or draft...",
"assistantTitle": "AI Assistant",
"assistantTitle": "AI Note",
"currentNote": "Current note",
"shrinkPanel": "Shrink panel",
"expandPanel": "Expand panel",
@@ -552,7 +552,7 @@
"insertedInNote": "Diagram inserted in note",
"insertExportError": "Error exporting/uploading diagram"
},
"openAssistant": "Open AI Assistant",
"openAssistant": "Open AI Note",
"poweredByMomento": "Powered by Momento AI",
"welcomeMsg": "Hello! I'm your AI assistant. How can I help you with your notes today? I can help refine tone, expand messaging, or summarize content.",
"summaryLast5": "Summary of your last 5 notes",
@@ -624,7 +624,9 @@
"presentationReadyBadge": "Presentation ready",
"openInLabTitle": "Open in Lab",
"inlineSummaryMarkdown": "**Summary:**",
"networkErrorShort": "Network error."
"networkErrorShort": "Network error.",
"featureLocked": "This feature requires the PRO plan or higher.",
"quotaExceeded": "Monthly limit reached. Resets next month."
},
"titleSuggestions": {
"available": "Title suggestions",
@@ -881,10 +883,11 @@
"showRecentNotes": "Show Recent Notes Section",
"showRecentNotesDescription": "Display recent notes (last 7 days) on the main page",
"recentNotesUpdateSuccess": "Recent notes setting updated successfully",
"recentNotesUpdateFailed": "Failed to update recent notes setting"
"recentNotesUpdateFailed": "Failed to update recent notes setting",
"tab": "Profile"
},
"aiSettings": {
"title": "AI Settings",
"title": "AI",
"description": "Configure your AI-powered features and preferences",
"features": "AI Features",
"provider": "AI Provider",
@@ -911,7 +914,8 @@
"autoLabeling": "Label suggestions",
"autoLabelingDesc": "Automatically suggests and applies labels to your notes",
"noteHistory": "Note history",
"noteHistoryDesc": "Enable version snapshots and restoration from History"
"noteHistoryDesc": "Enable version snapshots and restoration from History",
"titleSuggestions": "Title suggestions"
},
"general": {
"loading": "Loading...",
@@ -1173,6 +1177,8 @@
"deleteFailed": "Failed to delete",
"roleUpdateSuccess": "User role updated to {role}",
"roleUpdateFailed": "Failed to update role",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "Demote to User",
"promote": "Promote to Admin",
"confirmDelete": "Are you sure? This action cannot be undone.",
@@ -1180,6 +1186,7 @@
"name": "Name",
"email": "Email",
"role": "Role",
"subscription": "Subscription",
"createdAt": "Created At",
"actions": "Actions"
},
@@ -1317,7 +1324,8 @@
"documentation": "Documentation",
"reportIssues": "Report Issues",
"feedback": "Feedback"
}
},
"tab": "About"
},
"support": {
"title": "Support Memento Development",
@@ -1371,7 +1379,7 @@
"loading": "Loading..."
},
"dataManagement": {
"title": "Data Management",
"title": "Data",
"toolsDescription": "Tools to maintain your database health",
"exporting": "Exporting...",
"importing": "Importing...",
@@ -1433,7 +1441,8 @@
"fontSystem": "System Default",
"fontInterDefault": "Inter (default)",
"fontPlayfairDisplay": "Playfair Display",
"fontJetBrainsMono": "JetBrains Mono"
"fontJetBrainsMono": "JetBrains Mono",
"tab": "Appearance"
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -1452,10 +1461,15 @@
"proChat": "100 chat messages / month",
"later": "Later",
"upgradePricing": "Upgrade to Pro",
"addApiKey": "Use your own API key (BYOK)"
"addApiKey": "Use your own API key (BYOK)",
"featureReformulate": "Reformulations",
"featureChat": "AI Messages",
"featureBrainstormCreate": "Brainstorm creations",
"featureBrainstormExpand": "Brainstorm expansions",
"featureBrainstormEnrich": "Brainstorm enrichments"
},
"generalSettings": {
"title": "General Settings",
"title": "General",
"description": "General application settings"
},
"toast": {
@@ -1641,7 +1655,7 @@
"collapse": "Collapse"
},
"mcpSettings": {
"title": "MCP Settings",
"title": "MCP",
"description": "Manage API keys and configure external tools",
"whatIsMcp": {
"title": "What is MCP?",
@@ -2325,6 +2339,216 @@
"checkoutSuccessBody": "Welcome to {tier}. Your features are now unlocked.",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"tab": "Billing",
"currentUsage": "Current usage",
"currentPeriod": "Current period",
"aiCredits": "AI credits",
"used": "used",
"billing": "Billing",
"renewal": "Renewal",
"paidPlanDesc": "Your subscription renews automatically.",
"businessDescription": "For teams and product leaders."
},
"landing": {
"nav": {
"features": "Features",
"agents": "AI Agents",
"brainstorm": "Brainstorm",
"pricing": "Pricing",
"tech": "Architecture",
"login": "Log in",
"cta": "Get started"
},
"hero": {
"badge": "Powered by Artificial Intelligence",
"title1": "Your second brain,",
"title2": "finally amplified.",
"subtitle": "Momento is more than a note-taking app. It's an intelligent ecosystem that connects, analyzes and develops your ideas in real time with 6 types of AI agents and cutting-edge semantic search.",
"cta": "Sign up now",
"secondary": "See features",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"Connection detected with your sustainable design project from March 2024...\"",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12 ideas generated"
},
"features": {
"label": "AI Capabilities",
"title": "Fluid intelligence,",
"title2": "woven into every word.",
"desc": "Momento orchestrates your ideas through a multi-provider architecture.",
"f1Title": "Semantic Search",
"f1Desc": "Stop searching by keywords. Find by concept. Our hybrid Vector + FTS engine understands the intent behind your notes.",
"f2Title": "Contextual RAG Chat",
"f2Desc": "Chat with your knowledge. Our agents read your notes, explore the web and analyze your documents to respond with precision.",
"f3Title": "Augmented Writing",
"f3Desc": "Reformulation, title suggestions, auto-tagging and summaries. AI works in the background to structure your thinking."
},
"agents": {
"label": "Specialized Agents",
"title": "Delegate the complex work.",
"desc": "6 types of autonomous AI agents to automate your research, summaries and presentations.",
"scraper": {
"title": "Scraper",
"desc": "Scrapes URLs, parses RSS feeds and synthesizes information with smart image placement."
},
"researcher": {
"title": "Researcher",
"desc": "Generates complex queries, explores web sources and writes structured research notes."
},
"slideGen": {
"title": "Slide Gen",
"desc": "Transforms your notes into professional PowerPoint presentations or interactive HTML Slides."
},
"monitor": {
"title": "Monitor",
"desc": "Continuously analyzes your notebooks to detect trends and new insights."
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "Converts your ideas into fluid Excalidraw diagrams (Mindmaps, Flowcharts) with auto-layout."
},
"custom": {
"title": "Custom",
"desc": "Define your own agents with specific roles and data sources."
}
},
"brainstorm": {
"label": "Thought Waves",
"title": "Real-time radial brainstorming.",
"waveGeneration": {
"title": "Wave Generation",
"desc": "Variations, Analogies, then Disruptions. AI pushes your initial concept to its limits."
},
"collaboration": {
"title": "Native Collaboration",
"desc": "AI ghost cursors, synced avatars and real-time node movement."
},
"export": {
"title": "Semantic Export",
"desc": "Convert your entire brainstorm into structured notes in one click."
},
"disruptionLabel": "DISRUPTION",
"disruptionText": "Modular Architecture 2.0",
"analogyLabel": "ANALOGY",
"analogyText": "The tidal cycle"
},
"tech": {
"label": "Architecture & Providers",
"title": "Connect your own AI model.",
"tags": {
"title": "Tags",
"desc": "Independently configurable with any model."
},
"embeddings": {
"title": "Embeddings",
"desc": "Independently configurable with any model."
},
"chatRag": {
"title": "Chat RAG",
"desc": "Independently configurable with any model."
}
},
"pricing": {
"label": "Plans & Pricing",
"title": "Choose your level of amplification.",
"desc": "Flexible options for creative minds, from individual use to large organizations.",
"monthly": "Monthly",
"annual": "Annual",
"perMonth": "/month",
"perMonthAnnual": "/month, billed annually",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "Most popular",
"basic": {
"name": "Basic",
"desc": "Discover the magic of Momento.",
"cta": "Get started",
"feature0": "100 Notes max",
"feature1": "3 Notebooks",
"feature2": "50 AI credits (Lifetime)",
"feature3": "Semantic search",
"feature4": "7-day history"
},
"pro": {
"name": "Pro",
"desc": "For demanding consultants and creators.",
"cta": "Upgrade to Pro",
"feature0": "Unlimited notes",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "200 semantic searches",
"feature3": "Agents (12 runs/month)",
"feature4": "30-day history",
"feature5": "Email support"
},
"business": {
"name": "Business",
"desc": "For teams and product managers.",
"cta": "Choose Business",
"feature0": "10 Collaborators included",
"feature1": "BYOK (13 providers)",
"feature2": "1000 semantic searches",
"feature3": "Agents (60 runs/month)",
"feature4": "Unlimited brainstorming",
"feature5": "API access"
},
"enterprise": {
"name": "Enterprise",
"desc": "Secure organizational memory.",
"cta": "Contact Sales",
"feature0": "Everything in Business",
"feature1": "Unlimited agents",
"feature2": "SSO / SAML",
"feature3": "Audit Logs & SLA",
"feature4": "Dedicated support",
"feature5": "Live onboarding"
}
},
"byok": {
"label": "Open Cloud Technology",
"title": "The BYOK Strategy",
"desc": "Already have OpenAI, Anthropic or Google API keys? Connect them directly to Momento. Use AI without imposed credit limits, paying only what you actually consume from your favorite provider.",
"noLockin": "No lock-in",
"noLockinDesc": "Switch providers in 1 click.",
"cost": "Optimized costs",
"costDesc": "Pay the direct API price.",
"configLabel": "Multi-Provider Config"
},
"cta": {
"title1": "Ready to unlock your",
"title2": "full potential?",
"desc": "Join thousands of researchers, designers and thinkers already using Momento to build their future.",
"button": "Launch Momento"
},
"footer": {
"desc": "The AI-amplified second brain. Designed for creative minds.",
"product": {
"title": "Product",
"link0": "Changelog",
"link1": "Documentation",
"link2": "Roadmap",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "Community",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "Legal",
"link0": "Privacy Policy",
"link1": "Terms of Service",
"link2": "Cookie Policy",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -890,7 +890,7 @@
"recentNotesUpdateFailed": "Failed to update recent notes setting"
},
"aiSettings": {
"title": "Configuración IA",
"title": "AI",
"description": "Configura tus funciones y preferencias impulsadas por IA",
"features": "Funciones de IA",
"provider": "Proveedor de IA",
@@ -917,7 +917,8 @@
"autoLabeling": "Sugerencias de etiquetas",
"autoLabelingDesc": "Sugiere y aplica etiquetas automáticamente a tus notas",
"noteHistory": "Historial de notas",
"noteHistoryDesc": "Habilitar instantáneas de versiones y restauración desde el Historial"
"noteHistoryDesc": "Habilitar instantáneas de versiones y restauración desde el Historial",
"titleSuggestions": "Sugerencia de títulos"
},
"general": {
"loading": "Cargando...",
@@ -1115,7 +1116,13 @@
"languageDetection": "Detección de idioma",
"languageDetectionDesc": "Detecta automáticamente el idioma de cada nota",
"autoLabeling": "Etiquetado automático",
"autoLabelingDesc": "Sugiere y aplica etiquetas automáticamente"
"autoLabelingDesc": "Sugiere y aplica etiquetas automáticamente",
"fallbackSectionTitle": "Proveedor de respaldo (opcional)",
"fallbackSectionDescription": "Se usa automáticamente ante errores del proveedor (429, 5xx). Un reintento en 1,5 s.",
"fallbackProvider": "Proveedor de respaldo",
"fallbackModel": "Modelo de respaldo",
"fallbackNone": "Ninguno (desactivado)",
"fallbackModelPlaceholder": "p. ej. gpt-4o-mini"
},
"resend": {
"title": "Resend (Recomendado)",
@@ -1173,6 +1180,8 @@
"deleteFailed": "Error al eliminar",
"roleUpdateSuccess": "Rol de usuario actualizado a {role}",
"roleUpdateFailed": "Error al actualizar rol",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "Degradar",
"promote": "Promover",
"confirmDelete": "¿Estás seguro de que quieres eliminar este usuario?",
@@ -1180,6 +1189,7 @@
"name": "Nombre",
"email": "Correo electrónico",
"role": "Rol",
"subscription": "Subscription",
"createdAt": "Creado",
"actions": "Acciones"
},
@@ -1371,7 +1381,7 @@
"loading": "Cargando..."
},
"dataManagement": {
"title": "Data Management",
"title": "Data",
"toolsDescription": "Tools to maintain your database health",
"exporting": "Exportando",
"importing": "Importando",
@@ -1436,7 +1446,7 @@
"fontJetBrainsMono": "JetBrains Mono"
},
"generalSettings": {
"title": "Configuración general",
"title": "General",
"description": "Configuración general de la aplicación"
},
"toast": {
@@ -1622,7 +1632,7 @@
"collapse": "Colapsar"
},
"mcpSettings": {
"title": "Configuración MCP",
"title": "MCP",
"description": "Gestiona tus claves API y configura herramientas externas",
"whatIsMcp": {
"title": "¿Qué es MCP?",
@@ -2211,7 +2221,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "El anfitrión de la sesión ha alcanzado su límite de IA. Pídele que mejore su plan.",
"quotaHost": "Has alcanzado tu límite de IA para este brainstorm. Mejora tu plan para continuar."
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2323,6 +2335,215 @@
"checkoutSuccessBody": "Bienvenido a {tier}. Tus funciones están desbloqueadas.",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"currentUsage": "Uso actual",
"currentPeriod": "Período actual",
"aiCredits": "Créditos IA",
"used": "usados",
"billing": "Facturación",
"renewal": "Renovación",
"paidPlanDesc": "Su suscripción se renueva automáticamente.",
"businessDescription": "Para equipos y líderes de producto."
},
"landing": {
"nav": {
"features": "Funciones",
"agents": "Agentes IA",
"brainstorm": "Brainstorm",
"pricing": "Precios",
"tech": "Arquitectura",
"login": "Iniciar sesión",
"cta": "Empezar"
},
"hero": {
"badge": "Impulsado por inteligencia artificial",
"title1": "Tu segundo cerebro,",
"title2": "por fin amplificado.",
"subtitle": "Momento es más que una app de notas. Es un ecosistema inteligente que conecta, analiza y desarrolla tus ideas en tiempo real con 6 tipos de agentes IA y búsqueda semántica de vanguardia.",
"cta": "Regístrate ahora",
"secondary": "Ver funciones",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"Conexión detectada con tu proyecto de diseño sostenible de marzo de 2024...\"",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12 ideas generadas"
},
"features": {
"label": "Capacidades IA",
"title": "Inteligencia fluida,",
"title2": "tejida en cada palabra.",
"desc": "Momento orquesta tus ideas mediante una arquitectura multi-proveedor.",
"f1Title": "Búsqueda semántica",
"f1Desc": "Deja de buscar por palabras clave. Encuentra por concepto. Nuestro motor híbrido Vector + FTS entiende la intención detrás de tus notas.",
"f2Title": "Chat RAG contextual",
"f2Desc": "Conversa con tu conocimiento. Nuestros agentes leen tus notas, exploran la web y analizan tus documentos para responder con precisión.",
"f3Title": "Escritura aumentada",
"f3Desc": "Reformulación, sugerencias de títulos, etiquetado automático y resúmenes. La IA trabaja en segundo plano para estructurar tu pensamiento."
},
"agents": {
"label": "Agentes especializados",
"title": "Delega el trabajo complejo.",
"desc": "6 tipos de agentes IA autónomos para automatizar tu investigación, resúmenes y presentaciones.",
"scraper": {
"title": "Scraper",
"desc": "Extrae URLs, analiza feeds RSS y sintetiza información con colocación inteligente de imágenes."
},
"researcher": {
"title": "Researcher",
"desc": "Genera consultas complejas, explora fuentes web y redacta notas de investigación estructuradas."
},
"slideGen": {
"title": "Slide Gen",
"desc": "Transforma tus notas en presentaciones PowerPoint profesionales o diapositivas HTML interactivas."
},
"monitor": {
"title": "Monitor",
"desc": "Analiza continuamente tus cuadernos para detectar tendencias y nuevos insights."
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "Convierte tus ideas en diagramas Excalidraw fluidos (mapas mentales, diagramas de flujo) con auto-layout."
},
"custom": {
"title": "Custom",
"desc": "Define tus propios agentes con roles y fuentes de datos específicos."
}
},
"brainstorm": {
"label": "Olas de pensamiento",
"title": "Lluvia de ideas radial en tiempo real.",
"waveGeneration": {
"title": "Generación por olas",
"desc": "Variaciones, analogías y luego disrupciones. La IA lleva tu concepto inicial hasta sus límites."
},
"collaboration": {
"title": "Colaboración nativa",
"desc": "Cursores fantasma IA, avatares sincronizados y movimiento de nodos en tiempo real."
},
"export": {
"title": "Exportación semántica",
"desc": "Convierte toda tu sesión de brainstorming en notas estructuradas con un clic."
},
"disruptionLabel": "DISRUPCIÓN",
"disruptionText": "Arquitectura modular 2.0",
"analogyLabel": "ANALOGÍA",
"analogyText": "El ciclo de las mareas"
},
"tech": {
"label": "Arquitectura y proveedores",
"title": "Conecta tu propio modelo de IA.",
"tags": {
"title": "Tags",
"desc": "Configurable de forma independiente con cualquier modelo."
},
"embeddings": {
"title": "Embeddings",
"desc": "Configurable de forma independiente con cualquier modelo."
},
"chatRag": {
"title": "Chat RAG",
"desc": "Configurable de forma independiente con cualquier modelo."
}
},
"pricing": {
"label": "Planes y precios",
"title": "Elige tu nivel de amplificación.",
"desc": "Opciones flexibles para mentes creativas, del uso individual a grandes organizaciones.",
"monthly": "Mensual",
"annual": "Anual",
"perMonth": "/mes",
"perMonthAnnual": "/mes, facturado anualmente",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "Más popular",
"basic": {
"name": "Basic",
"desc": "Descubre la magia de Momento.",
"cta": "Empezar",
"feature0": "100 notas máx.",
"feature1": "3 cuadernos",
"feature2": "50 créditos IA (de por vida)",
"feature3": "Búsqueda semántica",
"feature4": "Historial 7 días"
},
"pro": {
"name": "Pro",
"desc": "Para consultores y creadores exigentes.",
"cta": "Pasar a Pro",
"feature0": "Notas ilimitadas",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "200 búsquedas semánticas",
"feature3": "Agentes (12 ejecuciones/mes)",
"feature4": "Historial 30 días",
"feature5": "Soporte por email"
},
"business": {
"name": "Business",
"desc": "Para equipos y product managers.",
"cta": "Elegir Business",
"feature0": "10 colaboradores incluidos",
"feature1": "BYOK (13 proveedores)",
"feature2": "1000 búsquedas semánticas",
"feature3": "Agentes (60 ejecuciones/mes)",
"feature4": "Brainstorm ilimitado",
"feature5": "Acceso API"
},
"enterprise": {
"name": "Enterprise",
"desc": "Memoria organizacional segura.",
"cta": "Contactar ventas",
"feature0": "Todo Business",
"feature1": "Agentes ilimitados",
"feature2": "SSO / SAML",
"feature3": "Audit Logs y SLA",
"feature4": "Soporte dedicado",
"feature5": "Onboarding en vivo"
}
},
"byok": {
"label": "Tecnología cloud abierta",
"title": "La estrategia BYOK",
"desc": "¿Ya tienes claves API de OpenAI, Anthropic o Google? Conéctalas directamente a Momento. Usa IA sin límites de crédito impuestos, pagando solo lo que consumes con tu proveedor favorito.",
"noLockin": "Sin lock-in",
"noLockinDesc": "Cambia de proveedor en 1 clic.",
"cost": "Costes optimizados",
"costDesc": "Paga el precio directo de la API.",
"configLabel": "Config multi-proveedor"
},
"cta": {
"title1": "¿Listo para liberar tu",
"title2": "máximo potencial?",
"desc": "Únete a miles de investigadores, diseñadores y pensadores que ya usan Momento para construir su futuro.",
"button": "Lanzar Momento"
},
"footer": {
"desc": "El segundo cerebro amplificado por IA. Diseñado para mentes creativas.",
"product": {
"title": "Producto",
"link0": "Changelog",
"link1": "Documentación",
"link2": "Roadmap",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "Comunidad",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "Legal",
"link0": "Política de privacidad",
"link1": "Términos de servicio",
"link2": "Política de cookies",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -463,8 +463,8 @@
"undoAI": "لغو تبدیل هوش مصنوعی",
"undoApplied": "متن اصلی بازگردانده شد",
"minWordsError": "یادداشت باید حداقل ۵ کلمه داشته باشد.",
"wordCountMin": "حداقل {min} کلمه برای بازنویسی انتخاب کنید (فعلاً {current} کلمه)",
"wordCountMax": "حداکثر {max} کلمه برای بازنویسی انتخاب کنید (فعلاً {current} کلمه)",
"wordCountMin": "حداقل {min} کلمه لازم است ({current} کلمه فعلی)",
"wordCountMax": "حداکثر {max} کلمه مجاز ({current} کلمه فعلی)",
"genericError": "خطای هوش مصنوعی",
"actionError": "خطا در حین عمل هوش مصنوعی",
"appliedToNote": "در یادداشت اعمال شد",
@@ -630,7 +630,9 @@
"creative": "Creative",
"academic": "Academic",
"casual": "Casual"
}
},
"featureLocked": "این قابلیت نیازمند طرح PRO یا بالاتر است.",
"quotaExceeded": "محدودیت ماهانه تکمیل شده. ماه آینده بازنشانی می‌شود."
},
"titleSuggestions": {
"available": "پیشنهادات عنوان",
@@ -887,10 +889,11 @@
"showRecentNotes": "نمایش بخش یادداشت‌های اخیر",
"showRecentNotesDescription": "نمایش یادداشت‌های اخیر (۷ روز گذشته) در صفحه اصلی",
"recentNotesUpdateSuccess": "تنظیم یادداشت‌های اخیر با موفقیت به‌روزرسانی شد",
"recentNotesUpdateFailed": "به‌روزرسانی تنظیم یادداشت‌های اخیر شکست خورد"
"recentNotesUpdateFailed": "به‌روزرسانی تنظیم یادداشت‌های اخیر شکست خورد",
"tab": "پروفایل"
},
"aiSettings": {
"title": "تنظیمات هوش مصنوعی",
"title": "هوش مصنوعی",
"description": "ویژگی‌ها و ترجیحات هوش مصنوعی خود را پیکربندی کنید",
"features": "ویژگی‌های هوش مصنوعی",
"provider": "فروشنده هوش مصنوعی",
@@ -917,7 +920,8 @@
"autoLabeling": "پیشنهاد برچسب",
"autoLabelingDesc": "به طور خودکار برچسب‌ها را به یادداشت‌های شما پیشنهاد و اعمال می‌کند",
"noteHistory": "تاریخچه یادداشت",
"noteHistoryDesc": "فعال‌سازی اسنپ‌شات نسخه‌ها و بازیابی از تاریخچه"
"noteHistoryDesc": "فعال‌سازی اسنپ‌شات نسخه‌ها و بازیابی از تاریخچه",
"titleSuggestions": "پیشنهاد عنوان"
},
"general": {
"loading": "در حال بارگذاری...",
@@ -1115,7 +1119,13 @@
"languageDetection": "تشخیص زبان",
"languageDetectionDesc": "تشخیص خودکار زبان هر یادداشت",
"autoLabeling": "برچسب‌گذاری خودکار",
"autoLabelingDesc": "پیشنهاد و اعمال خودکار برچسب‌ها"
"autoLabelingDesc": "پیشنهاد و اعمال خودکار برچسب‌ها",
"fallbackSectionTitle": "ارائه‌دهنده پشتیبان (اختیاری)",
"fallbackSectionDescription": "در صورت خطای ارائه‌دهنده (429، 5xx) به‌صورت خودکار استفاده می‌شود. یک تلاش مجدد در ۱,۵ ثانیه.",
"fallbackProvider": "ارائه‌دهنده پشتیبان",
"fallbackModel": "مدل پشتیبان",
"fallbackNone": "هیچ (غیرفعال)",
"fallbackModelPlaceholder": "مثلاً gpt-4o-mini"
},
"resend": {
"title": "Resend (پیشنهادی)",
@@ -1173,6 +1183,8 @@
"deleteFailed": "شکست در حذف",
"roleUpdateSuccess": "نقش کاربر به {role} به‌روزرسانی شد",
"roleUpdateFailed": "شکست در به‌روزرسانی نقش",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "تنزل",
"promote": "ارتقا",
"confirmDelete": "مطمئن هستید؟ این عمل قابل بازگشت نیست.",
@@ -1180,6 +1192,7 @@
"name": "نام",
"email": "ایمیل",
"role": "نقش",
"subscription": "Subscription",
"createdAt": "تاریخ ایجاد",
"actions": "عملیات"
},
@@ -1317,7 +1330,8 @@
"documentation": "مستندات",
"reportIssues": "گزارش مشکلات",
"feedback": "بازخورد"
}
},
"tab": "درباره"
},
"support": {
"title": "پشتیبانی از توسعه Memento",
@@ -1371,7 +1385,7 @@
"loading": "در حال بارگذاری..."
},
"dataManagement": {
"title": "مدیریت داده",
"title": "دادهها",
"toolsDescription": "ابزارهایی برای حفظ سلامت پایگاه داده",
"exporting": "در حال صادرات...",
"importing": "در حال وارد کردن...",
@@ -1433,10 +1447,11 @@
"fontSystem": "فونت پیش‌فرض سیستم",
"fontInterDefault": "Inter (default)",
"fontPlayfairDisplay": "Playfair Display",
"fontJetBrainsMono": "JetBrains Mono"
"fontJetBrainsMono": "JetBrains Mono",
"tab": "ظاهر"
},
"generalSettings": {
"title": "تنظیمات عمومی",
"title": "عمومی",
"description": "تنظیمات عمومی برنامه"
},
"toast": {
@@ -1622,7 +1637,7 @@
"collapse": "جمع کردن"
},
"mcpSettings": {
"title": "تنظیمات MCP",
"title": "MCP",
"description": "مدیریت کلیدهای API و پیکربندی ابزارهای خارجی",
"whatIsMcp": {
"title": "MCP چیست؟",
@@ -2211,7 +2226,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "میزبان جلسه به سقف هوش مصنوعی رسیده. از او بخواهید طرحش را ارتقا دهد.",
"quotaHost": "به سقف هوش مصنوعی این طوفان فکری رسیدید. برای ادامه، طرح خود را ارتقا دهید."
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2230,7 +2247,12 @@
"proChat": "100 chat messages / month",
"later": "Later",
"upgradePricing": "Upgrade to Pro",
"addApiKey": "Use your own API key (BYOK)"
"addApiKey": "Use your own API key (BYOK)",
"featureReformulate": "بازنویسی",
"featureChat": "پیام‌های هوش مصنوعی",
"featureBrainstormCreate": "ایجاد طوفان فکری",
"featureBrainstormExpand": "گسترش طوفان فکری",
"featureBrainstormEnrich": "غنی‌سازی طوفان فکری"
},
"byokSettings": {
"title": "Your API keys (BYOK)",
@@ -2323,6 +2345,216 @@
"checkoutSuccessBody": "به {tier} خوش آمدید. ویژگی‌های شما اکنون باز شده‌اند.",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"tab": "صورتحساب",
"currentUsage": "مصرف فعلی",
"currentPeriod": "دوره جاری",
"aiCredits": "اعتبار هوش مصنوعی",
"used": "استفاده شده",
"billing": "صورتحساب",
"renewal": "تمدید",
"paidPlanDesc": "اشتراک شما به‌طور خودکار تمدید می‌شود.",
"businessDescription": "برای تیم‌ها و مدیران محصول."
},
"landing": {
"nav": {
"features": "امکانات",
"agents": "دستیاران هوشمند",
"brainstorm": "طوفان فکری",
"pricing": "تعرفه‌ها",
"tech": "ساختار فنی",
"login": "ورود",
"cta": "شروع کنید"
},
"hero": {
"badge": "توانمند با هوش مصنوعی",
"title1": "مغز دوم شما،",
"title2": "حالا قوی‌تر از همیشه.",
"subtitle": "مومنتو یه noting app ساده نیست؛ یه سیستم هوشمندی‌ه که با ۶ نوع دستیار AI و جستجوی معنایی پیشرفته، لحظه‌به‌لحظه به ایده‌هاتون جان می‌بخشه و پخش‌شون می‌کنه.",
"cta": "همین الان ثبت‌نام کنید",
"secondary": "امکانات رو ببینید",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"ارتباط پیدا شد با پروژه طراحی پایدار شما از مارس ۲۰۲۴...\"",
"brainstormLive": "طوفان فکری زنده",
"ideasGenerated": "+۱۲ ایده تولید شد"
},
"features": {
"label": "توانایی‌های هوشمند",
"title": "هوشی روان و بی‌وقفه،",
"title2": "نفوذکرده در هر کلمه.",
"desc": "مومنتو با معماری چندمنبعی، ایده‌هاتون رو هماهنگ و مدیریت می‌کنه.",
"f1Title": "جستجوی معنایی",
"f1Desc": "کلمه‌کلیدی دور ریخته. اینجا معنا مهمه. موتور ترکیبی ما منظور پشت نوشته‌هاتون رو می‌فهمه، نه فقط کلماتش رو.",
"f2Title": "چت هوشمند و آگاه",
"f2Desc": "با دانش خودتون حرف بزنید. دستیارهای ما یادداشت‌هاتون رو می‌خونن، وب رو می‌گردن و اسناد رو تحلیل می‌کنن تا دقیق‌ترین جواب رو بهتون بدن.",
"f3Title": "نوشتار هوشمند",
"f3Desc": "از بازنویسی و پیشنهاد عنوان گرفته تا برچسب‌گذاری و خلاصه‌سازی خودکار — AI همیشه توی پس‌زمینه کار می‌کنه تا افکارتون منظم بشه."
},
"agents": {
"label": "دستیاران تخصصی",
"title": "کارای سخت رو بسپارید به ما.",
"desc": "۶ نوع دستیار هوشمند و خودکار برای راحت‌کردن تحقیق، خلاصه‌سازی و ارائه‌هاتون.",
"scraper": {
"title": "Scraper",
"desc": "آدرس‌ها رو اسکرپ می‌کنه، فیدهای RSS رو پردازش می‌کنه و اطلاعات رو با جایگذاری هوشمند تصاویر خلاصه‌سازی می‌کنه."
},
"researcher": {
"title": "Researcher",
"desc": "کوئری‌های پیچیده تولید می‌کنه، منابع وب رو کاوش می‌کنه و یادداشت‌های تحقیقاتی ساختاریافته می‌نویسه."
},
"slideGen": {
"title": "Slide Gen",
"desc": "یادداشت‌هاتون رو به ارائه‌های حرفه‌ای PowerPoint یا اسلایدهای HTML تعاملی تبدیل می‌کنه."
},
"monitor": {
"title": "Monitor",
"desc": "دائماً دفترچه‌هاتون رو تحلیل می‌کنه تا روند‌ها و بینش‌های جدید رو شناسایی کنه."
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "ایده‌هاتون رو به نمودارهای Excalidraw روان (مپ ذهنی، فلوچارت) با چیدمان خودکار تبدیل می‌کنه."
},
"custom": {
"title": "Custom",
"desc": "دستیارهای اختصاصی خودتون رو با نقش‌ها و منابع داده خاص تعریف کنید."
}
},
"brainstorm": {
"label": "امواج ایده",
"title": "طوفان فکری شعاعی و زنده.",
"waveGeneration": {
"title": "تولید موجی",
"desc": "تنوع، تشبیه، بعدش اختلال. AI مفهوم اولیه شما رو تا مرزهاش می‌چرخونه."
},
"collaboration": {
"title": "همکاری ذاتی",
"desc": "کرسرهای شبح AI، آواتارهای همگام‌شده و جابجایی گره‌ها در زمان واقعی."
},
"export": {
"title": "خروجی معنایی",
"desc": "کل طوفان فکری‌تون رو با یه کلیک به یادداشت‌های ساختاریافته تبدیل کنید."
},
"disruptionLabel": "اختلال",
"disruptionText": "معماری ماژولار ۲.۰",
"analogyLabel": "تشبیه",
"analogyText": "چرخه جزر و مد"
},
"tech": {
"label": "ساختار و ارائه‌دهندگان",
"title": "مدل AI خودتون رو وصل کنید.",
"tags": {
"title": "برچسب‌ها",
"desc": "مستقل از هر مدلی قابل تنظیم."
},
"embeddings": {
"title": "Embeddings",
"desc": "مستقل از هر مدلی قابل تنظیم."
},
"chatRag": {
"title": "Chat RAG",
"desc": "مستقل از هر مدلی قابل تنظیم."
}
},
"pricing": {
"label": "پلن‌ها و تعرفه‌ها",
"title": "سطح توانمندی خودتون رو انتخاب کنید.",
"desc": "گزینه‌های منعطف برای ذهن‌های خلاق — از استفاده شخصی تا سازمان‌های بزرگ.",
"monthly": "ماهانه",
"annual": "سالانه",
"perMonth": "/ماه",
"perMonthAnnual": "/ماه، پرداخت سالانه",
"perUser": "+ ۳,۹۰€/کاربر",
"perUserAnnual": "+ ۲,۹۰€/کاربر، پرداخت سالانه",
"popular": "پرطرفدارترین",
"basic": {
"name": "Basic",
"desc": "ذوق مومنتو رو بچشید.",
"cta": "شروع کنید",
"feature0": "حداکثر ۱۰۰ یادداشت",
"feature1": "۳ دفترچه",
"feature2": "۵۰ اعتبار AI (مادام‌العمر)",
"feature3": "جستجوی معنایی",
"feature4": "تاریخچه ۷ روزه"
},
"pro": {
"name": "Pro",
"desc": "برای مشاوران و خالق‌های سخت‌گیر.",
"cta": "ارتقا به پرو",
"feature0": "یادداشت نامحدود",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "۲۰۰ جستجوی معنایی",
"feature3": "دستیارها (۱۲ اجرا/ماه)",
"feature4": "تاریخچه ۳۰ روزه",
"feature5": "پشتیبانی ایمیل"
},
"business": {
"name": "Business",
"desc": "برای تیم‌ها و مدیران محصول.",
"cta": "انتخاب بیزینس",
"feature0": "۱۰ همکار شامل",
"feature1": "BYOK (۱۳ ارائه‌دهنده)",
"feature2": "۱۰۰۰ جستجوی معنایی",
"feature3": "دستیارها (۶۰ اجرا/ماه)",
"feature4": "طوفان فکری نامحدود",
"feature5": "دسترسی API"
},
"enterprise": {
"name": "Enterprise",
"desc": "حافظه سازمانی امن.",
"cta": "تماس با فروش",
"feature0": "همه امکانات بیزینس",
"feature1": "دستیارهای نامحدود",
"feature2": "SSO / SAML",
"feature3": "لاگ حسابرسی و SLA",
"feature4": "پشتیبانی اختصاصی",
"feature5": "آنبوردینگ زنده"
}
},
"byok": {
"label": "زیرساخت ابری باز",
"title": "استراتژی BYOK",
"desc": "کلید API اپن‌ای، آنتروپیک یا گوگل دارید؟ مستقیم وصلش کنید به مومنتو. بدون محدودیت اعتبار، فقط همون‌قدر هزینه می‌کنید که واقعاً مصرف کردید.",
"noLockin": "بدون قفل‌شدگی",
"noLockinDesc": "با یه کلیک ارائه‌دهنده عوض کنید.",
"cost": "هزینه بهینه",
"costDesc": "همون قیمت مستقیم API رو می‌دید.",
"configLabel": "تنظیمات چندمنبعی"
},
"cta": {
"title1": "آماده‌اید",
"title2": "استعداد واقعیتون رو شکوفا کنید؟",
"desc": "به هزاران پژوهشگر، طراح و متفکر ملحق بشید که از مومنتو برای ساختن آینده‌شون استفاده می‌کنن.",
"button": "اجرا مومنتو"
},
"footer": {
"desc": "مغز دوم هوشمند با AI. طراحی‌شده برای ذهن‌های خلاق.",
"product": {
"title": "محصول",
"link0": "تغییرات",
"link1": "مستندات",
"link2": "نقشه راه",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "جامعه",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "حقوقی",
"link0": "حریم خصوصی",
"link1": "شرایط استفاده",
"link2": "سیاست کوکی",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -463,8 +463,8 @@
"undoAI": "Annuler la transformation IA",
"undoApplied": "Texte original restauré",
"minWordsError": "La note doit contenir au moins 5 mots pour utiliser les actions IA.",
"wordCountMin": "Veuillez sélectionner au moins {min} mots pour reformuler ({current} mots sélectionnés)",
"wordCountMax": "Veuillez sélectionner au maximum {max} mots pour reformuler ({current} mots sélectionnés)",
"wordCountMin": "Minimum {min} mots requis ({current} actuels)",
"wordCountMax": "Maximum {max} mots autorisés ({current} actuels)",
"genericError": "Erreur IA",
"actionError": "Erreur lors de l'action IA",
"appliedToNote": "Appliqué à la note",
@@ -630,7 +630,9 @@
"presentationReadyBadge": "Présentation prête",
"openInLabTitle": "Ouvrir dans le Lab",
"inlineSummaryMarkdown": "**Résumé :**",
"networkErrorShort": "Erreur réseau."
"networkErrorShort": "Erreur réseau.",
"featureLocked": "Cette fonctionnalité nécessite le plan PRO ou supérieur.",
"quotaExceeded": "Limite mensuelle atteinte. Se réinitialise le mois prochain."
},
"titleSuggestions": {
"available": "Suggestions de titre",
@@ -887,10 +889,11 @@
"showRecentNotes": "Afficher la section Récent",
"showRecentNotesDescription": "Afficher les notes récentes (7 derniers jours) sur la page principale",
"recentNotesUpdateSuccess": "Paramètre des notes récentes mis à jour avec succès",
"recentNotesUpdateFailed": "Échec de la mise à jour du paramètre des notes récentes"
"recentNotesUpdateFailed": "Échec de la mise à jour du paramètre des notes récentes",
"tab": "Profil"
},
"aiSettings": {
"title": "Paramètres IA",
"title": "IA",
"description": "Configurez vos fonctionnalités IA et préférences",
"features": "Fonctionnalités IA",
"provider": "Fournisseur IA",
@@ -917,7 +920,8 @@
"autoLabeling": "Suggestion des labels",
"autoLabelingDesc": "Suggère et applique des étiquettes automatiquement à vos notes",
"noteHistory": "Historique des notes",
"noteHistoryDesc": "Active les snapshots de versions et la restauration depuis History"
"noteHistoryDesc": "Active les snapshots de versions et la restauration depuis History",
"titleSuggestions": "Suggestion de titres"
},
"general": {
"loading": "Chargement...",
@@ -1179,6 +1183,8 @@
"deleteFailed": "Échec de la suppression",
"roleUpdateSuccess": "Rôle de l'utilisateur mis à jour à {role}",
"roleUpdateFailed": "Échec de la mise à jour du rôle",
"tierUpdateSuccess": "Abonnement mis à jour à {tier}",
"tierUpdateFailed": "Échec de la mise à jour de l'abonnement",
"demote": "Rétrograder en utilisateur",
"promote": "Promouvoir en admin",
"confirmDelete": "Êtes-vous sûr ? Cette action est irréversible.",
@@ -1186,6 +1192,7 @@
"name": "Nom",
"email": "Courriel",
"role": "Rôle",
"subscription": "Abonnement",
"createdAt": "Créé le",
"actions": "Actions"
},
@@ -1323,7 +1330,8 @@
"documentation": "Documentation",
"reportIssues": "Signaler des problèmes",
"feedback": "Commentaires"
}
},
"tab": "À propos"
},
"support": {
"title": "Supporter le développement de Memento",
@@ -1377,7 +1385,7 @@
"loading": "Chargement..."
},
"dataManagement": {
"title": "Gestion des données",
"title": "Données",
"toolsDescription": "Outils pour maintenir la santé de votre base de données",
"exporting": "Exportation...",
"importing": "Importation...",
@@ -1439,7 +1447,8 @@
"fontSystem": "Police système par défaut",
"fontInterDefault": "Inter (défaut)",
"fontPlayfairDisplay": "Playfair Display",
"fontJetBrainsMono": "JetBrains Mono"
"fontJetBrainsMono": "JetBrains Mono",
"tab": "Apparence"
},
"usageMeter": {
"packName": "Pack découverte IA",
@@ -1458,10 +1467,15 @@
"proChat": "100 messages de chat / mois",
"later": "Plus tard",
"upgradePricing": "Passer à Pro",
"addApiKey": "Utiliser votre propre clé API (BYOK)"
"addApiKey": "Utiliser votre propre clé API (BYOK)",
"featureReformulate": "Reformulations",
"featureChat": "Messages IA",
"featureBrainstormCreate": "Créations brainstorm",
"featureBrainstormExpand": "Extensions brainstorm",
"featureBrainstormEnrich": "Enrichissements brainstorm"
},
"generalSettings": {
"title": "Paramètres généraux",
"title": "Généraux",
"description": "Paramètres généraux de l'application"
},
"toast": {
@@ -1647,7 +1661,7 @@
"collapse": "Réduire"
},
"mcpSettings": {
"title": "Paramètres MCP",
"title": "MCP",
"description": "Gérez vos clés API et configurez les outils externes",
"whatIsMcp": {
"title": "Qu'est-ce que MCP ?",
@@ -2331,6 +2345,216 @@
"checkoutSuccessBody": "Bienvenue sur {tier}. Vos fonctionnalités sont maintenant débloquées.",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"tab": "Facturation",
"currentUsage": "Utilisation actuelle",
"currentPeriod": "Période en cours",
"aiCredits": "Crédits IA",
"used": "utilisés",
"billing": "Facturation",
"renewal": "Renouvellement",
"paidPlanDesc": "Votre abonnement se renouvelle automatiquement.",
"businessDescription": "Pour les équipes et chefs de produit."
},
"landing": {
"nav": {
"features": "Fonctionnalités",
"agents": "Agents IA",
"brainstorm": "Brainstorm",
"pricing": "Tarifs",
"tech": "Architecture",
"login": "Se connecter",
"cta": "Commencez"
},
"hero": {
"badge": "Augmenté par l'Intelligence Artificielle",
"title1": "Votre second cerveau,",
"title2": "enfin amplifié.",
"subtitle": "Momento n'est pas qu'une simple application de notes. C'est un écosystème intelligent qui connecte, analyse et développe vos idées en temps réel grâce à 6 types d'agents IA et une recherche sémantique de pointe.",
"cta": "S'inscrire maintenant",
"secondary": "Voir les fonctionnalités",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"Connexion détectée avec votre projet de design durable de Mars 2024...\"",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12 idées générées"
},
"features": {
"label": "Capacités IA",
"title": "Une intelligence fluide,",
"title2": "intégrée à chaque mot.",
"desc": "Momento orchestre vos idées grâce à une architecture multi-fournisseurs.",
"f1Title": "Recherche Sémantique",
"f1Desc": "Ne cherchez plus par mots-clés. Trouvez par concept. Notre moteur hybride Vector + FTS comprend l'intention derrière vos notes.",
"f2Title": "Chat RAG Contextuel",
"f2Desc": "Discutez avec votre savoir. Nos agents lisent vos notes, explorent le web et analysent vos documents pour répondre avec précision.",
"f3Title": "Écriture Augmentée",
"f3Desc": "Reformulation, suggestions de titres, tagging automatique et résumés. L'IA travaille en arrière-plan pour structurer votre pensée."
},
"agents": {
"label": "Agents Spécialisés",
"title": "Déléguez le travail complexe.",
"desc": "6 types d'agents IA autonomes pour automatiser vos recherches, vos résumés et vos présentations.",
"scraper": {
"title": "Scraper",
"desc": "Scrape des URLs, parse les flux RSS et synthétise l'info avec placement d'images intelligent."
},
"researcher": {
"title": "Researcher",
"desc": "Génère des requêtes complexes, explore les sources web et rédige des notes de recherche structurées."
},
"slideGen": {
"title": "Slide Gen",
"desc": "Transforme vos notes en présentations PowerPoint professionnelles ou Slides HTML Interactives."
},
"monitor": {
"title": "Monitor",
"desc": "Analyse continuellement vos carnets pour détecter les tendances et les nouveaux insights."
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "Convertit vos idées en diagrammes Excalidraw fluides (Mindmaps, Flowcharts) avec auto-layout."
},
"custom": {
"title": "Custom",
"desc": "Définissez vos propres agents avec des rôles et des sources de données spécifiques."
}
},
"brainstorm": {
"label": "Vagues de Pensée",
"title": "Brainstorming radial en temps réel.",
"waveGeneration": {
"title": "Génération par Vagues",
"desc": "Variations, Analogies, puis Disruptions. L'IA pousse votre concept initial dans ses retranchements."
},
"collaboration": {
"title": "Collaboration Native",
"desc": "Curseurs fantômes IA, avatars synchronisés et déplacement de nœuds en temps réel."
},
"export": {
"title": "Export Sémantique",
"desc": "Convertissez tout votre brainstorm en notes structurées d'un seul clic."
},
"disruptionLabel": "DISRUPTION",
"disruptionText": "Architecture Modulaire 2.0",
"analogyLabel": "ANALOGIE",
"analogyText": "Le cycle des marées"
},
"tech": {
"label": "Architecture & Fournisseurs",
"title": "Connectez votre propre intelligence.",
"tags": {
"title": "Tags",
"desc": "Indépendamment configurable avec n'importe quel modèle."
},
"embeddings": {
"title": "Embeddings",
"desc": "Indépendamment configurable avec n'importe quel modèle."
},
"chatRag": {
"title": "Chat RAG",
"desc": "Indépendamment configurable avec n'importe quel modèle."
}
},
"pricing": {
"label": "Plans & Tarification",
"title": "Choisissez votre niveau d'amplification.",
"desc": "Des options flexibles pour les esprits créatifs, de l'usage individuel aux grandes organisations.",
"monthly": "Mensuel",
"annual": "Annuel",
"perMonth": "/mois",
"perMonthAnnual": "/mois, facturé annuellement",
"perUser": "+ 3,90€/user",
"perUserAnnual": "+ 2,90€/user, facturé annuellement",
"popular": "Le plus populaire",
"basic": {
"name": "Basic",
"desc": "Pour découvrir la magie de Momento.",
"cta": "Commencer",
"feature0": "100 Notes max",
"feature1": "3 Carnets",
"feature2": "50 crédits IA (Lifetime)",
"feature3": "Recherche sémantique",
"feature4": "Historique 7 jours"
},
"pro": {
"name": "Pro",
"desc": "Pour les consultants et créateurs exigeants.",
"cta": "Passer Pro",
"feature0": "Notes illimitées",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "200 recherches sémantiques",
"feature3": "Agents (12 runs/mois)",
"feature4": "Historique 30 jours",
"feature5": "Support Email"
},
"business": {
"name": "Business",
"desc": "Pour les équipes et chefs de produit.",
"cta": "Choisir Business",
"feature0": "10 Collaborateurs inclus",
"feature1": "BYOK (13 fournisseurs)",
"feature2": "1000 recherches sémantiques",
"feature3": "Agents (60 runs/mois)",
"feature4": "Brainstorm illimité",
"feature5": "Accès API"
},
"enterprise": {
"name": "Enterprise",
"desc": "Mémoire organisationnelle sécurisée.",
"cta": "Contacter Ventes",
"feature0": "Tout Business",
"feature1": "Agents illimités",
"feature2": "SSO / SAML",
"feature3": "Audit Logs & SLA",
"feature4": "Support Dédié",
"feature5": "Onboarding Live"
}
},
"byok": {
"label": "Technologie Cloud Ouverte",
"title": "La stratégie BYOK",
"desc": "Vous possédez déjà des clés API OpenAI, Anthropic ou Google ? Connectez-les directement à Momento. Utilisez l'IA sans limites de crédits imposées, en payant uniquement ce que vous consommez chez votre fournisseur favori.",
"noLockin": "Pas de lock-in",
"noLockinDesc": "Changez de fournisseur en 1 clic.",
"cost": "Coûts optimisés",
"costDesc": "Payez le prix direct API.",
"configLabel": "Config Multi-Fournisseurs"
},
"cta": {
"title1": "Prêt à libérer votre",
"title2": "plein potentiel ?",
"desc": "Rejoignez des milliers de chercheurs, designers et penseurs qui utilisent déjà Momento pour construire leur futur.",
"button": "Lancer Momento"
},
"footer": {
"desc": "Le second cerveau amplifié par l'IA. Pensé pour les esprits créatifs.",
"product": {
"title": "Produit",
"link0": "Changelog",
"link1": "Documentation",
"link2": "Roadmap",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "Communauté",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "Légal",
"link0": "Politique de confidentialité",
"link1": "Conditions d'utilisation",
"link2": "Cookies",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -890,7 +890,7 @@
"recentNotesUpdateFailed": "Failed to update recent notes setting"
},
"aiSettings": {
"title": "AI सेटिंग्स",
"title": "AI",
"description": "अपनी AI-संचालित सुविधाओं और प्राथमिकताओं को कॉन्फ़िगर करें",
"features": "AI सुविधाएं",
"provider": "AI प्रदाता",
@@ -917,7 +917,8 @@
"autoLabeling": "सुझावों को लेबल करें",
"autoLabelingDesc": "स्वचालित रूप से आपके नोट्स पर लेबल सुझाता है और लागू करता है",
"noteHistory": "इतिहास नोट करें",
"noteHistoryDesc": "इतिहास से संस्करण स्नैपशॉट और पुनर्स्थापना सक्षम करें"
"noteHistoryDesc": "इतिहास से संस्करण स्नैपशॉट और पुनर्स्थापना सक्षम करें",
"titleSuggestions": "शीर्षक सुझाव"
},
"general": {
"loading": "लोड हो रहा है...",
@@ -1115,7 +1116,13 @@
"languageDetection": "भाषा पहचान",
"languageDetectionDesc": "प्रत्येक नोट की भाषा का स्वचालित पता लगाएं",
"autoLabeling": "स्वतः लेबलिंग",
"autoLabelingDesc": "लेबल स्वचालित रूप से सुझाएँ और लागू करें"
"autoLabelingDesc": "लेबल स्वचालित रूप से सुझाएँ और लागू करें",
"fallbackSectionTitle": "फ़ॉलबैक प्रदाता (वैकल्पिक)",
"fallbackSectionDescription": "प्रदाता त्रुटियों (429, 5xx) पर स्वतः उपयोग। 1.5 सेकंड में एक पुनः प्रयास।",
"fallbackProvider": "फ़ॉलबैक प्रदाता",
"fallbackModel": "फ़ॉलबैक मॉडल",
"fallbackNone": "कोई नहीं (अक्षम)",
"fallbackModelPlaceholder": "उदा. gpt-4o-mini"
},
"resend": {
"title": "Resend (अनुशंसित)",
@@ -1173,6 +1180,8 @@
"deleteFailed": "हटाने में विफल",
"roleUpdateSuccess": "उपयोगकर्ता भूमिका को {role} में अपडेट किया गया",
"roleUpdateFailed": "भूमिका अपडेट करने में विफल",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "अवमत करें",
"promote": "पदोन्नत करें",
"confirmDelete": "Are you sure? This action cannot be undone.",
@@ -1180,6 +1189,7 @@
"name": "नाम",
"email": "ईमेल",
"role": "भूमिका",
"subscription": "Subscription",
"createdAt": "बनाया गया",
"actions": "कार्रवाई"
},
@@ -1371,7 +1381,7 @@
"loading": "लोड हो रहा है..."
},
"dataManagement": {
"title": "डेटा प्रबंधन",
"title": "Data",
"toolsDescription": "अपने डेटाबेस स्वास्थ्य को बनाए रखने के लिए उपकरण",
"exporting": "निर्यात हो रहा है...",
"importing": "आयात हो रहा है...",
@@ -1436,7 +1446,7 @@
"fontJetBrainsMono": "JetBrains Mono"
},
"generalSettings": {
"title": "सामान्य सेटिंग्स",
"title": "General",
"description": "सामान्य एप्लिकेशन सेटिंग्स"
},
"toast": {
@@ -1622,7 +1632,7 @@
"collapse": "संकुचित करें"
},
"mcpSettings": {
"title": "MCP सेटिंग्स",
"title": "MCP",
"description": "API कुंजियाँ प्रबंधित करें और बाहरी टूल कॉन्फ़िगर करें",
"whatIsMcp": {
"title": "MCP क्या है?",
@@ -2211,7 +2221,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "सत्र के होस्ट की AI सीमा समाप्त हो गई है। उनसे अपना प्लान अपग्रेड करने को कहें।",
"quotaHost": "इस ब्रेनस्टॉर्म के लिए आपकी AI सीमा समाप्त हो गई है। जारी रखने के लिए प्लान अपग्रेड करें।"
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2323,6 +2335,215 @@
"checkoutSuccessBody": "{tier} में आपका स्वागत है।",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"currentUsage": "वर्तमान उपयोग",
"currentPeriod": "वर्तमान अवधि",
"aiCredits": "AI क्रेडिट",
"used": "उपयोग किया",
"billing": "बिलिंग",
"renewal": "नवीनीकरण",
"paidPlanDesc": "आपकी सदस्यता स्वचालित रूप से नवीनीकरण होती है।",
"businessDescription": "टीमों और उत्पाद नेताओं के लिए।"
},
"landing": {
"nav": {
"features": "सुविधाएँ",
"agents": "AI एजेंट",
"brainstorm": "Brainstorm",
"pricing": "मूल्य",
"tech": "आर्किटेक्चर",
"login": "लॉग इन",
"cta": "शुरू करें"
},
"hero": {
"badge": "कृत्रिम बुद्धिमत्ता से संचालित",
"title1": "आपका दूसरा दिमाग,",
"title2": "आखिरकार प्रबलित।",
"subtitle": "Momento सिर्फ़ नोट ऐप नहीं है। यह एक बुद्धिमान इकोसिस्टम है जो 6 प्रकार के AI एजेंट और अत्याधुनिक सिमैंटिक खोज के साथ आपके विचारों को रियल टाइम में जोड़ता, विश्लेषण करता और विकसित करता है।",
"cta": "अभी साइन अप करें",
"secondary": "सुविधाएँ देखें",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"मार्च 2024 के आपके सतत डिज़ाइन प्रोजेक्ट से कनेक्शन मिला...\"",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12 विचार जनरेट"
},
"features": {
"label": "AI क्षमताएँ",
"title": "प्रवाही बुद्धि,",
"title2": "हर शब्द में बुनी हुई।",
"desc": "Momento मल्टी-प्रोवाइडर आर्किटेक्चर से आपके विचारों को व्यवस्थित करता है।",
"f1Title": "सिमैंटिक खोज",
"f1Desc": "कीवर्ड से खोजना छोड़ें। अवधारणा से खोजें। हमारा हाइब्रिड Vector + FTS इंजन आपके नोट्स के पीछे के इरादे को समझता है।",
"f2Title": "संदर्भित RAG चैट",
"f2Desc": "अपने ज्ञान से बात करें। हमारे एजेंट नोट्स पढ़ते हैं, वेब खोजते हैं और दस्तावेज़ विश्लेषण कर सटीक उत्तर देते हैं।",
"f3Title": "संवर्धित लेखन",
"f3Desc": "पुनर्लेखन, शीर्षक सुझाव, ऑटो-टैगिंग और सारांश। AI पृष्ठभूमि में आपकी सोच को संरचित करता है।"
},
"agents": {
"label": "विशेषज्ञ एजेंट",
"title": "जटिल काम सौंपें।",
"desc": "6 प्रकार के स्वायत्त AI एजेंट आपके शोध, सारांश और प्रस्तुतियों को स्वचालित करते हैं।",
"scraper": {
"title": "Scraper",
"desc": "URL स्क्रैप करता है, RSS पार्स करता है और स्मार्ट इमेज प्लेसमेंट के साथ जानकारी संश्लेषित करता है।"
},
"researcher": {
"title": "Researcher",
"desc": "जटिल क्वेरी बनाता है, वेब स्रोत खोजता है और संरचित शोध नोट्स लिखता है।"
},
"slideGen": {
"title": "Slide Gen",
"desc": "आपके नोट्स को प्रोफेशनल PowerPoint या इंटरैक्टिव HTML स्लाइड में बदलता है।"
},
"monitor": {
"title": "Monitor",
"desc": "ट्रेंड और नई अंतर्दृष्टि के लिए आपके नोटबुक का निरंतर विश्लेषण करता है।"
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "विचारों को Excalidraw के प्रवाही आरेख (माइंडमैप, फ्लोचार्ट) में ऑटो-लेआउट के साथ बदलता है।"
},
"custom": {
"title": "Custom",
"desc": "विशिष्ट भूमिकाओं और डेटा स्रोतों के साथ अपने एजेंट परिभाषित करें।"
}
},
"brainstorm": {
"label": "विचार की लहरें",
"title": "रियल टाइम रेडियल ब्रेनस्टॉर्मिंग।",
"waveGeneration": {
"title": "वेव जनरेशन",
"desc": "विविधता, सादृश्य, फिर व्यवधान। AI आपकी प्रारंभिक अवधारणा को उसकी सीमा तक धकेलता है।"
},
"collaboration": {
"title": "मूल सहयोग",
"desc": "AI घोस्ट कर्सर, सिंक अवतार और रियल टाइम नोड मूवमेंट।"
},
"export": {
"title": "सिमैंटिक निर्यात",
"desc": "पूरा ब्रेनस्टॉर्म एक क्लिक में संरचित नोट्स में बदलें।"
},
"disruptionLabel": "व्यवधान",
"disruptionText": "मॉड्यूलर आर्किटेक्चर 2.0",
"analogyLabel": "सादृश्य",
"analogyText": "ज्वार का चक्र"
},
"tech": {
"label": "आर्किटेक्चर और प्रोवाइडर",
"title": "अपना AI मॉडल कनेक्ट करें।",
"tags": {
"title": "Tags",
"desc": "किसी भी मॉडल के साथ स्वतंत्र रूप से कॉन्फ़िगर करने योग्य।"
},
"embeddings": {
"title": "Embeddings",
"desc": "किसी भी मॉडल के साथ स्वतंत्र रूप से कॉन्फ़िगर करने योग्य।"
},
"chatRag": {
"title": "Chat RAG",
"desc": "किसी भी मॉडल के साथ स्वतंत्र रूप से कॉन्फ़िगर करने योग्य।"
}
},
"pricing": {
"label": "प्लान और मूल्य",
"title": "अपना प्रबलन स्तर चुनें।",
"desc": "रचनात्मक दिमागों के लिए लचीले विकल्प — व्यक्तिगत उपयोग से बड़े संगठनों तक।",
"monthly": "मासिक",
"annual": "वार्षिक",
"perMonth": "/माह",
"perMonthAnnual": "/माह, वार्षिक बिलिंग",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "सबसे लोकप्रिय",
"basic": {
"name": "Basic",
"desc": "Momento का जादू खोजें।",
"cta": "शुरू करें",
"feature0": "अधिकतम 100 नोट",
"feature1": "3 नोटबुक",
"feature2": "50 AI क्रेडिट (आजीवन)",
"feature3": "सिमैंटिक खोज",
"feature4": "7 दिन का इतिहास"
},
"pro": {
"name": "Pro",
"desc": "मांग वाले सलाहकारों और रचनाकारों के लिए।",
"cta": "Pro में अपग्रेड",
"feature0": "असीमित नोट",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "200 सिमैंटिक खोज",
"feature3": "एजेंट (12 रन/माह)",
"feature4": "30 दिन का इतिहास",
"feature5": "ईमेल सहायता"
},
"business": {
"name": "Business",
"desc": "टीमों और प्रोडक्ट मैनेजरों के लिए।",
"cta": "Business चुनें",
"feature0": "10 सहयोगी शामिल",
"feature1": "BYOK (13 प्रोवाइडर)",
"feature2": "1000 सिमैंटिक खोज",
"feature3": "एजेंट (60 रन/माह)",
"feature4": "असीमित ब्रेनस्टॉर्म",
"feature5": "API एक्सेस"
},
"enterprise": {
"name": "Enterprise",
"desc": "सुरक्षित संगठनात्मक स्मृति।",
"cta": "बिक्री से संपर्क",
"feature0": "Business की सब कुछ",
"feature1": "असीमित एजेंट",
"feature2": "SSO / SAML",
"feature3": "Audit Logs और SLA",
"feature4": "समर्पित सहायता",
"feature5": "लाइव ऑनबोर्डिंग"
}
},
"byok": {
"label": "ओपन क्लाउड तकनीक",
"title": "BYOK रणनीति",
"desc": "पहले से OpenAI, Anthropic या Google API कुंजी हैं? सीधे Momento से जोड़ें। बिना लागू क्रेडिट सीमा के AI उपयोग करें, केवल पसंदीदा प्रोवाइडर पर वास्तविक खपत का भुगतान करें।",
"noLockin": "कोई लॉक-इन नहीं",
"noLockinDesc": "1 क्लिक में प्रोवाइडर बदलें।",
"cost": "अनुकूलित लागत",
"costDesc": "सीधी API कीमत चुकाएँ।",
"configLabel": "मल्टी-प्रोवाइडर कॉन्फ़िग"
},
"cta": {
"title1": "अपनी",
"title2": "पूरी क्षमता खोलने के लिए तैयार?",
"desc": "हज़ारों शोधकर्ताओं, डिज़ाइनरों और विचारकों से जुड़ें जो Momento से अपना भविष्य बना रहे हैं।",
"button": "Momento लॉन्च करें"
},
"footer": {
"desc": "AI-प्रबलित दूसरा दिमाग। रचनात्मक दिमागों के लिए।",
"product": {
"title": "उत्पाद",
"link0": "चेंजलॉग",
"link1": "दस्तावेज़",
"link2": "रोडमैप",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "समुदाय",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "कानूनी",
"link0": "गोपनीयता",
"link1": "सेवा की शर्तें",
"link2": "कुकी नीति",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -400,7 +400,7 @@
"transformError": "Error during transformation",
"convertToRichtext": "Converti in Rich Text",
"convertingToRichtext": "Conversione...",
"assistant": "AI Assistant",
"assistant": "AI Note",
"generating": "Generating...",
"generateTitles": "Generate titles",
"reformulateText": "Reformulate text",
@@ -890,7 +890,7 @@
"recentNotesUpdateFailed": "Failed to update recent notes setting"
},
"aiSettings": {
"title": "Impostazioni AI",
"title": "AI",
"description": "Configura le funzionalità AI e le preferenze",
"features": "Funzionalità AI",
"provider": "Provider AI",
@@ -917,7 +917,8 @@
"autoLabeling": "Suggerimenti per le etichette",
"autoLabelingDesc": "Suggerisce e applica automaticamente le etichette alle tue note",
"noteHistory": "Nota la storia",
"noteHistoryDesc": "Abilita gli snapshot della versione e il ripristino dalla cronologia"
"noteHistoryDesc": "Abilita gli snapshot della versione e il ripristino dalla cronologia",
"titleSuggestions": "Suggerimento titoli"
},
"general": {
"loading": "Caricamento...",
@@ -1115,7 +1116,13 @@
"languageDetection": "Rilevamento lingua",
"languageDetectionDesc": "Rileva automaticamente la lingua di ogni nota",
"autoLabeling": "Etichettatura automatica",
"autoLabelingDesc": "Suggerisce e applica etichette automaticamente"
"autoLabelingDesc": "Suggerisce e applica etichette automaticamente",
"fallbackSectionTitle": "Provider di riserva (opzionale)",
"fallbackSectionDescription": "Usato automaticamente in caso di errori del provider (429, 5xx). Un solo nuovo tentativo entro 1,5 s.",
"fallbackProvider": "Provider di riserva",
"fallbackModel": "Modello di riserva",
"fallbackNone": "Nessuno (disattivato)",
"fallbackModelPlaceholder": "es. gpt-4o-mini"
},
"resend": {
"title": "Resend (Consigliato)",
@@ -1173,6 +1180,8 @@
"deleteFailed": "Failed to delete",
"roleUpdateSuccess": "User role updated to {role}",
"roleUpdateFailed": "Failed to update role",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "Declassa",
"promote": "Promuovi",
"confirmDelete": "Sei sicuro di voler eliminare questo utente?",
@@ -1180,6 +1189,7 @@
"name": "Name",
"email": "Email",
"role": "Role",
"subscription": "Subscription",
"createdAt": "Created At",
"actions": "Actions"
},
@@ -1371,7 +1381,7 @@
"loading": "Caricamento..."
},
"dataManagement": {
"title": "Data Management",
"title": "Data",
"toolsDescription": "Tools to maintain your database health",
"exporting": "Esportazione in corso...",
"importing": "Importazione in corso...",
@@ -1436,7 +1446,7 @@
"fontJetBrainsMono": "JetBrains Mono"
},
"generalSettings": {
"title": "Impostazioni generali",
"title": "General",
"description": "Impostazioni generali dell'applicazione"
},
"toast": {
@@ -1622,7 +1632,7 @@
"collapse": "Comprimi"
},
"mcpSettings": {
"title": "Impostazioni MCP",
"title": "MCP",
"description": "Gestisci le chiavi API e configura gli strumenti esterni",
"whatIsMcp": {
"title": "Cos'è MCP?",
@@ -2211,7 +2221,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "L'host della sessione ha raggiunto il limite IA. Chiedigli di aggiornare il piano.",
"quotaHost": "Hai raggiunto il limite IA per questo brainstorm. Passa a un piano superiore per continuare."
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2323,6 +2335,215 @@
"checkoutSuccessBody": "Benvenuto su {tier}. Le tue funzionalità sono ora sbloccate.",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"currentUsage": "Utilizzo attuale",
"currentPeriod": "Periodo corrente",
"aiCredits": "Crediti IA",
"used": "utilizzati",
"billing": "Fatturazione",
"renewal": "Rinnovo",
"paidPlanDesc": "Il tuo abbonamento si rinnova automaticamente.",
"businessDescription": "Per team e responsabili di prodotto."
},
"landing": {
"nav": {
"features": "Funzionalità",
"agents": "Agenti IA",
"brainstorm": "Brainstorm",
"pricing": "Prezzi",
"tech": "Architettura",
"login": "Accedi",
"cta": "Inizia"
},
"hero": {
"badge": "Potenziato dall'intelligenza artificiale",
"title1": "Il tuo secondo cervello,",
"title2": "finalmente amplificato.",
"subtitle": "Momento è più di un'app per appunti. È un ecosistema intelligente che collega, analizza e sviluppa le tue idee in tempo reale con 6 tipi di agenti IA e ricerca semantica all'avanguardia.",
"cta": "Registrati ora",
"secondary": "Scopri le funzionalità",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"Connessione rilevata con il tuo progetto di design sostenibile di marzo 2024...\"",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12 idee generate"
},
"features": {
"label": "Capacità IA",
"title": "Intelligenza fluida,",
"title2": "intrecciata in ogni parola.",
"desc": "Momento orchestra le tue idee attraverso un'architettura multi-provider.",
"f1Title": "Ricerca semantica",
"f1Desc": "Smetti di cercare per parole chiave. Trova per concetto. Il nostro motore ibrido Vector + FTS comprende l'intento dietro le tue note.",
"f2Title": "Chat RAG contestuale",
"f2Desc": "Parla con la tua conoscenza. I nostri agenti leggono le tue note, esplorano il web e analizzano i documenti per rispondere con precisione.",
"f3Title": "Scrittura aumentata",
"f3Desc": "Riformulazione, suggerimenti di titoli, tagging automatico e riassunti. L'IA lavora in background per strutturare il tuo pensiero."
},
"agents": {
"label": "Agenti specializzati",
"title": "Delega il lavoro complesso.",
"desc": "6 tipi di agenti IA autonomi per automatizzare ricerche, riassunti e presentazioni.",
"scraper": {
"title": "Scraper",
"desc": "Estrae URL, analizza feed RSS e sintetizza informazioni con posizionamento intelligente delle immagini."
},
"researcher": {
"title": "Researcher",
"desc": "Genera query complesse, esplora fonti web e scrive note di ricerca strutturate."
},
"slideGen": {
"title": "Slide Gen",
"desc": "Trasforma le tue note in presentazioni PowerPoint professionali o slide HTML interattive."
},
"monitor": {
"title": "Monitor",
"desc": "Analizza continuamente i tuoi quaderni per rilevare tendenze e nuovi insight."
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "Converte le tue idee in diagrammi Excalidraw fluidi (mappe mentali, flowchart) con auto-layout."
},
"custom": {
"title": "Custom",
"desc": "Definisci agenti personalizzati con ruoli e fonti dati specifici."
}
},
"brainstorm": {
"label": "Onde di pensiero",
"title": "Brainstorming radiale in tempo reale.",
"waveGeneration": {
"title": "Generazione a onde",
"desc": "Variazioni, analogie e poi disruption. L'IA spinge il tuo concetto iniziale ai suoi limiti."
},
"collaboration": {
"title": "Collaborazione nativa",
"desc": "Cursori fantasma IA, avatar sincronizzati e spostamento nodi in tempo reale."
},
"export": {
"title": "Export semantico",
"desc": "Converti l'intero brainstorming in note strutturate con un clic."
},
"disruptionLabel": "DISRUPTION",
"disruptionText": "Architettura modulare 2.0",
"analogyLabel": "ANALOGIA",
"analogyText": "Il ciclo delle maree"
},
"tech": {
"label": "Architettura e provider",
"title": "Collega il tuo modello IA.",
"tags": {
"title": "Tags",
"desc": "Configurabile indipendentemente con qualsiasi modello."
},
"embeddings": {
"title": "Embeddings",
"desc": "Configurabile indipendentemente con qualsiasi modello."
},
"chatRag": {
"title": "Chat RAG",
"desc": "Configurabile indipendentemente con qualsiasi modello."
}
},
"pricing": {
"label": "Piani e prezzi",
"title": "Scegli il tuo livello di amplificazione.",
"desc": "Opzioni flessibili per menti creative, dall'uso individuale alle grandi organizzazioni.",
"monthly": "Mensile",
"annual": "Annuale",
"perMonth": "/mese",
"perMonthAnnual": "/mese, fatturato annualmente",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "Più popolare",
"basic": {
"name": "Basic",
"desc": "Scopri la magia di Momento.",
"cta": "Inizia",
"feature0": "100 note max",
"feature1": "3 quaderni",
"feature2": "50 crediti IA (a vita)",
"feature3": "Ricerca semantica",
"feature4": "Cronologia 7 giorni"
},
"pro": {
"name": "Pro",
"desc": "Per consulenti e creatori esigenti.",
"cta": "Passa a Pro",
"feature0": "Note illimitate",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "200 ricerche semantiche",
"feature3": "Agenti (12 esecuzioni/mese)",
"feature4": "Cronologia 30 giorni",
"feature5": "Supporto email"
},
"business": {
"name": "Business",
"desc": "Per team e product manager.",
"cta": "Scegli Business",
"feature0": "10 collaboratori inclusi",
"feature1": "BYOK (13 provider)",
"feature2": "1000 ricerche semantiche",
"feature3": "Agenti (60 esecuzioni/mese)",
"feature4": "Brainstorm illimitato",
"feature5": "Accesso API"
},
"enterprise": {
"name": "Enterprise",
"desc": "Memoria organizzativa sicura.",
"cta": "Contatta vendite",
"feature0": "Tutto Business",
"feature1": "Agenti illimitati",
"feature2": "SSO / SAML",
"feature3": "Audit Logs e SLA",
"feature4": "Supporto dedicato",
"feature5": "Onboarding live"
}
},
"byok": {
"label": "Tecnologia cloud aperta",
"title": "La strategia BYOK",
"desc": "Hai già chiavi API OpenAI, Anthropic o Google? Collegale direttamente a Momento. Usa l'IA senza limiti di credito imposti, pagando solo ciò che consumi dal tuo provider preferito.",
"noLockin": "Nessun lock-in",
"noLockinDesc": "Cambia provider in 1 clic.",
"cost": "Costi ottimizzati",
"costDesc": "Paga il prezzo API diretto.",
"configLabel": "Config multi-provider"
},
"cta": {
"title1": "Pronto a liberare il tuo",
"title2": "pieno potenziale?",
"desc": "Unisciti a migliaia di ricercatori, designer e pensatori che usano già Momento per costruire il loro futuro.",
"button": "Avvia Momento"
},
"footer": {
"desc": "Il secondo cervello amplificato dall'IA. Pensato per menti creative.",
"product": {
"title": "Prodotto",
"link0": "Changelog",
"link1": "Documentazione",
"link2": "Roadmap",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "Community",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "Legale",
"link0": "Privacy",
"link1": "Termini di servizio",
"link2": "Cookie",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -890,7 +890,7 @@
"recentNotesUpdateFailed": "最近のノート設定の更新に失敗しました"
},
"aiSettings": {
"title": "AI設定",
"title": "AI",
"description": "AI機能と設定を構成",
"features": "AI機能",
"provider": "AIプロバイダー",
@@ -917,7 +917,8 @@
"autoLabeling": "ラベルの提案",
"autoLabelingDesc": "ラベルを自動的に提案してメモに適用します",
"noteHistory": "メモ履歴",
"noteHistoryDesc": "バージョンのスナップショットと履歴からの復元を有効にする"
"noteHistoryDesc": "バージョンのスナップショットと履歴からの復元を有効にする",
"titleSuggestions": "タイトル提案"
},
"general": {
"loading": "読み込み中...",
@@ -1115,7 +1116,13 @@
"languageDetection": "言語検出",
"languageDetectionDesc": "各ノートの言語を自動検出",
"autoLabeling": "自動ラベリング",
"autoLabelingDesc": "ラベルを自動で提案・適用"
"autoLabelingDesc": "ラベルを自動で提案・適用",
"fallbackSectionTitle": "フォールバックプロバイダー(任意)",
"fallbackSectionDescription": "プロバイダーエラー時429、5xxに自動使用。1.5秒以内に1回再試行。",
"fallbackProvider": "フォールバックプロバイダー",
"fallbackModel": "フォールバックモデル",
"fallbackNone": "なし(無効)",
"fallbackModelPlaceholder": "例: gpt-4o-mini"
},
"resend": {
"title": "Resend推奨",
@@ -1173,6 +1180,8 @@
"deleteFailed": "削除に失敗しました",
"roleUpdateSuccess": "ユーザーの役割が{role}に更新されました",
"roleUpdateFailed": "役割の更新に失敗しました",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "降格",
"promote": "昇格",
"confirmDelete": "よろしいですか?この操作は元に戻せません。",
@@ -1180,6 +1189,7 @@
"name": "名前",
"email": "メール",
"role": "役割",
"subscription": "Subscription",
"createdAt": "作成日",
"actions": "アクション"
},
@@ -1371,7 +1381,7 @@
"loading": "読み込み中..."
},
"dataManagement": {
"title": "データ管理",
"title": "Data",
"toolsDescription": "データベースの健全性を維持するツール",
"exporting": "エクスポート中...",
"importing": "インポート中...",
@@ -1436,7 +1446,7 @@
"fontJetBrainsMono": "JetBrains Mono"
},
"generalSettings": {
"title": "一般設定",
"title": "General",
"description": "一般的なアプリケーション設定"
},
"toast": {
@@ -1622,7 +1632,7 @@
"collapse": "折りたたむ"
},
"mcpSettings": {
"title": "MCP設定",
"title": "MCP",
"description": "APIキーの管理と外部ツールの設定",
"whatIsMcp": {
"title": "MCPとは",
@@ -2211,7 +2221,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "セッションのホストがAI利用上限に達しました。プランのアップグレードを依頼してください。",
"quotaHost": "このブレインストームのAI上限に達しました。続けるにはプランをアップグレードしてください。"
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2323,6 +2335,215 @@
"checkoutSuccessBody": "{tier}へようこそ。機能が解放されました。",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"currentUsage": "現在の使用量",
"currentPeriod": "現在の期間",
"aiCredits": "AIクレジット",
"used": "使用済み",
"billing": "請求",
"renewal": "更新",
"paidPlanDesc": "サブスクリプションは自動更新されます。",
"businessDescription": "チームとプロダクトリーダー向け。"
},
"landing": {
"nav": {
"features": "機能",
"agents": "AIエージェント",
"brainstorm": "Brainstorm",
"pricing": "料金",
"tech": "アーキテクチャ",
"login": "ログイン",
"cta": "はじめる"
},
"hero": {
"badge": "人工知能で強化",
"title1": "あなたの第二の脳、",
"title2": "ついに増幅される。",
"subtitle": "Momentoは単なるメモアプリではありません。6種類のAIエージェントと最先端のセマンティック検索で、アイデアをリアルタイムに接続・分析・発展させるインテリジェントなエコシステムです。",
"cta": "今すぐ登録",
"secondary": "機能を見る",
"memoryEcho": "Memory Echo",
"memoryEchoText": "「2024年3月のサステナブルデザインプロジェクトとの関連を検出しました...」",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12件のアイデアを生成"
},
"features": {
"label": "AI機能",
"title": "流れるような知性、",
"title2": "言葉のひとつひとつに織り込まれる。",
"desc": "Momentoはマルチプロバイダーアーキテクチャでアイデアを統合します。",
"f1Title": "セマンティック検索",
"f1Desc": "キーワード検索はもう不要。概念で探せます。ハイブリッドのVector + FTSエンジンがートの意図を理解します。",
"f2Title": "コンテキストRAGチャット",
"f2Desc": "知識と対話できます。エージェントがートを読み、Webを探索し、文書を分析して正確に回答します。",
"f3Title": "拡張ライティング",
"f3Desc": "言い換え、タイトル提案、自動タグ付け、要約。AIがバックグラウンドで思考を整理します。"
},
"agents": {
"label": "専門エージェント",
"title": "複雑な作業を任せましょう。",
"desc": "調査・要約・プレゼンを自動化する6種類の自律型AIエージェント。",
"scraper": {
"title": "Scraper",
"desc": "URLを取得しRSSを解析、画像配置も賢く情報を統合します。"
},
"researcher": {
"title": "Researcher",
"desc": "複雑なクエリを生成しWebソースを探索、構造化された調査ートを作成します。"
},
"slideGen": {
"title": "Slide Gen",
"desc": "ートをプロ品質のPowerPointやインタラクティブHTMLスライドに変換します。"
},
"monitor": {
"title": "Monitor",
"desc": "ノートブックを継続分析し、トレンドや新しいインサイトを検出します。"
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "アイデアをExcalidrawの滑らかな図マインドマップ、フローチャートに自動レイアウトで変換します。"
},
"custom": {
"title": "Custom",
"desc": "役割とデータソースを指定した独自エージェントを定義できます。"
}
},
"brainstorm": {
"label": "思考の波",
"title": "リアルタイムの放射状ブレインストーム。",
"waveGeneration": {
"title": "ウェーブ生成",
"desc": "バリエーション、アナロジー、そしてディスラプション。AIが初期コンセプトを限界まで押し広げます。"
},
"collaboration": {
"title": "ネイティブコラボレーション",
"desc": "AIゴーストカーソル、同期アバター、ードのリアルタイム移動。"
},
"export": {
"title": "セマンティックエクスポート",
"desc": "ブレインストーム全体をワンクリックで構造化ノートに変換。"
},
"disruptionLabel": "ディスラプション",
"disruptionText": "モジュラーアーキテクチャ 2.0",
"analogyLabel": "アナロジー",
"analogyText": "潮汐のサイクル"
},
"tech": {
"label": "アーキテクチャとプロバイダー",
"title": "独自のAIモデルを接続。",
"tags": {
"title": "Tags",
"desc": "任意のモデルで独立して設定可能。"
},
"embeddings": {
"title": "Embeddings",
"desc": "任意のモデルで独立して設定可能。"
},
"chatRag": {
"title": "Chat RAG",
"desc": "任意のモデルで独立して設定可能。"
}
},
"pricing": {
"label": "プランと料金",
"title": "増幅レベルを選びましょう。",
"desc": "個人利用から大規模組織まで、クリエイティブな方に柔軟な選択肢。",
"monthly": "月額",
"annual": "年額",
"perMonth": "/月",
"perMonthAnnual": "/月(年払い)",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "最も人気",
"basic": {
"name": "Basic",
"desc": "Momentoの魔法を体験。",
"cta": "はじめる",
"feature0": "最大100ート",
"feature1": "3ートブック",
"feature2": "AIクレジット50生涯",
"feature3": "セマンティック検索",
"feature4": "7日間の履歴"
},
"pro": {
"name": "Pro",
"desc": "高い要求を持つコンサル・クリエイター向け。",
"cta": "Proにアップグレード",
"feature0": "無制限ノート",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "セマンティック検索200回",
"feature3": "エージェント月12回",
"feature4": "30日間の履歴",
"feature5": "メールサポート"
},
"business": {
"name": "Business",
"desc": "チームとプロダクトマネージャー向け。",
"cta": "Businessを選択",
"feature0": "10名のコラボレーター込み",
"feature1": "BYOK13プロバイダー",
"feature2": "セマンティック検索1000回",
"feature3": "エージェント月60回",
"feature4": "無制限ブレインストーム",
"feature5": "APIアクセス"
},
"enterprise": {
"name": "Enterprise",
"desc": "安全な組織メモリ。",
"cta": "営業に問い合わせ",
"feature0": "Businessの全機能",
"feature1": "無制限エージェント",
"feature2": "SSO / SAML",
"feature3": "監査ログとSLA",
"feature4": "専任サポート",
"feature5": "ライブオンボーディング"
}
},
"byok": {
"label": "オープンクラウド技術",
"title": "BYOK戦略",
"desc": "OpenAI、Anthropic、GoogleのAPIキーをお持ちですかMomentoに直接接続。クレジット上限なしで、お好みのプロバイダーの実消費分だけお支払い。",
"noLockin": "ロックインなし",
"noLockinDesc": "ワンクリックでプロバイダー変更。",
"cost": "最適化されたコスト",
"costDesc": "APIの直接価格で支払い。",
"configLabel": "マルチプロバイダー設定"
},
"cta": {
"title1": "あなたの",
"title2": "可能性を解き放つ準備はできましたか?",
"desc": "Momentoで未来を築く研究者、デザイナー、思想家の仲間入りを。",
"button": "Momentoを起動"
},
"footer": {
"desc": "AIで増幅された第二の脳。クリエイティブな方のために。",
"product": {
"title": "製品",
"link0": "変更履歴",
"link1": "ドキュメント",
"link2": "ロードマップ",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "コミュニティ",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "法的情報",
"link0": "プライバシー",
"link1": "利用規約",
"link2": "Cookie",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -890,7 +890,7 @@
"recentNotesUpdateFailed": "최근 노트 설정 업데이트 실패"
},
"aiSettings": {
"title": "AI 설정",
"title": "AI",
"description": "AI 기반 기능 및 환경설정 구성",
"features": "AI 기능",
"provider": "AI 공급자",
@@ -917,7 +917,8 @@
"autoLabeling": "라벨 제안",
"autoLabelingDesc": "노트에 라벨을 자동으로 제안하고 적용합니다.",
"noteHistory": "메모 기록",
"noteHistoryDesc": "버전 스냅샷 및 기록 복원 활성화"
"noteHistoryDesc": "버전 스냅샷 및 기록 복원 활성화",
"titleSuggestions": "제목 제안"
},
"general": {
"loading": "로딩 중...",
@@ -1115,7 +1116,13 @@
"languageDetection": "언어 감지",
"languageDetectionDesc": "각 노트의 언어 자동 감지",
"autoLabeling": "자동 라벨링",
"autoLabelingDesc": "라벨 자동 제안 및 적용"
"autoLabelingDesc": "라벨 자동 제안 및 적용",
"fallbackSectionTitle": "대체 제공업체(선택)",
"fallbackSectionDescription": "제공업체 오류(429, 5xx) 시 자동 사용. 1.5초 이내 1회 재시도.",
"fallbackProvider": "대체 제공업체",
"fallbackModel": "대체 모델",
"fallbackNone": "없음(비활성화)",
"fallbackModelPlaceholder": "예: gpt-4o-mini"
},
"resend": {
"title": "Resend (권장)",
@@ -1173,6 +1180,8 @@
"deleteFailed": "삭제 실패",
"roleUpdateSuccess": "사용자 역할이 {role}(으)로 업데이트되었습니다",
"roleUpdateFailed": "역할 업데이트 실패",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "강등",
"promote": "승격",
"confirmDelete": "확실합니까? 이 작업은 되돌릴 수 없습니다.",
@@ -1180,6 +1189,7 @@
"name": "이름",
"email": "이메일",
"role": "역할",
"subscription": "Subscription",
"createdAt": "생성일",
"actions": "작업"
},
@@ -1371,7 +1381,7 @@
"loading": "로딩 중..."
},
"dataManagement": {
"title": "데이터 관리",
"title": "Data",
"toolsDescription": "데이터베이스 상태를 유지하는 도구",
"exporting": "내보내는 중...",
"importing": "가져오는 중...",
@@ -1436,7 +1446,7 @@
"fontJetBrainsMono": "JetBrains Mono"
},
"generalSettings": {
"title": "일반 설정",
"title": "General",
"description": "일반 애플리케이션 설정"
},
"toast": {
@@ -1622,7 +1632,7 @@
"collapse": "접기"
},
"mcpSettings": {
"title": "MCP 설정",
"title": "MCP",
"description": "API 키 관리 및 외부 도구 구성",
"whatIsMcp": {
"title": "MCP란 무엇인가요?",
@@ -2211,7 +2221,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "세션 호스트의 AI 한도에 도달했습니다. 플랜 업그레이드를 요청하세요.",
"quotaHost": "이 브레인스토밍의 AI 한도에 도달했습니다. 계속하려면 플랜을 업그레이드하세요."
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2323,6 +2335,215 @@
"checkoutSuccessBody": "{tier}에 오신 것을 환영합니다.",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"currentUsage": "현재 사용량",
"currentPeriod": "현재 기간",
"aiCredits": "AI 크레딧",
"used": "사용됨",
"billing": "결제",
"renewal": "갱신",
"paidPlanDesc": "구독이 자동으로 갱신됩니다.",
"businessDescription": "팀 및 프로덕트 리더를 위한 요금제."
},
"landing": {
"nav": {
"features": "기능",
"agents": "AI 에이전트",
"brainstorm": "Brainstorm",
"pricing": "요금",
"tech": "아키텍처",
"login": "로그인",
"cta": "시작하기"
},
"hero": {
"badge": "인공지능으로 구동",
"title1": "당신의 제2의 뇌,",
"title2": "드디어 증폭됩니다.",
"subtitle": "Momento는 단순한 메모 앱이 아닙니다. 6종류의 AI 에이전트와 최첨단 시맨틱 검색으로 아이디어를 실시간으로 연결·분석·발전시키는 지능형 생태계입니다.",
"cta": "지금 가입하기",
"secondary": "기능 보기",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"2024년 3월 지속 가능 디자인 프로젝트와의 연결 감지...\"",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12개 아이디어 생성"
},
"features": {
"label": "AI 역량",
"title": "유연한 지능,",
"title2": "모든 단어에 스며듭니다.",
"desc": "Momento는 멀티 프로바이더 아키텍처로 아이디어를 조율합니다.",
"f1Title": "시맨틱 검색",
"f1Desc": "키워드 검색은 그만. 개념으로 찾으세요. 하이브리드 Vector + FTS 엔진이 노트 뒤의 의도를 이해합니다.",
"f2Title": "컨텍스트 RAG 채팅",
"f2Desc": "지식과 대화하세요. 에이전트가 노트를 읽고, 웹을 탐색하며, 문서를 분석해 정확히 답합니다.",
"f3Title": "증강 글쓰기",
"f3Desc": "재작성, 제목 제안, 자동 태깅, 요약. AI가 백그라운드에서 사고를 구조화합니다."
},
"agents": {
"label": "전문 에이전트",
"title": "복잡한 작업을 위임하세요.",
"desc": "연구, 요약, 프레젠테이션을 자동화하는 6종류의 자율 AI 에이전트.",
"scraper": {
"title": "Scraper",
"desc": "URL을 수집하고 RSS를 파싱하며 이미지 배치까지 똑똑하게 정보를 종합합니다."
},
"researcher": {
"title": "Researcher",
"desc": "복잡한 쿼리를 생성하고 웹 소스를 탐색해 구조화된 연구 노트를 작성합니다."
},
"slideGen": {
"title": "Slide Gen",
"desc": "노트를 전문 PowerPoint 또는 인터랙티브 HTML 슬라이드로 변환합니다."
},
"monitor": {
"title": "Monitor",
"desc": "노트북을 지속 분석해 트렌드와 새로운 인사이트를 감지합니다."
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "아이디어를 Excalidraw의 유려한 다이어그램(마인드맵, 플로차트)으로 자동 배치합니다."
},
"custom": {
"title": "Custom",
"desc": "역할과 데이터 소스를 지정한 맞춤 에이전트를 정의하세요."
}
},
"brainstorm": {
"label": "사고의 파동",
"title": "실시간 방사형 브레인스토밍.",
"waveGeneration": {
"title": "웨이브 생성",
"desc": "변형, 유추, 그다음 파괴적 혁신. AI가 초기 개념을 한계까지 밀어냅니다."
},
"collaboration": {
"title": "네이티브 협업",
"desc": "AI 고스트 커서, 동기화된 아바타, 실시간 노드 이동."
},
"export": {
"title": "시맨틱보내기",
"desc": "브레인스토밍 전체를 한 번의 클릭으로 구조화된 노트로 변환."
},
"disruptionLabel": "파괴적 혁신",
"disruptionText": "모듈형 아키텍처 2.0",
"analogyLabel": "유추",
"analogyText": "조석의 리듬"
},
"tech": {
"label": "아키텍처 및 프로바이더",
"title": "자신만의 AI 모델을 연결하세요.",
"tags": {
"title": "Tags",
"desc": "어떤 모델과도 독립적으로 설정 가능."
},
"embeddings": {
"title": "Embeddings",
"desc": "어떤 모델과도 독립적으로 설정 가능."
},
"chatRag": {
"title": "Chat RAG",
"desc": "어떤 모델과도 독립적으로 설정 가능."
}
},
"pricing": {
"label": "플랜 및 요금",
"title": "증폭 수준을 선택하세요.",
"desc": "개인 사용부터 대규모 조직까지, 창의적인 분들을 위한 유연한 옵션.",
"monthly": "월간",
"annual": "연간",
"perMonth": "/월",
"perMonthAnnual": "/월, 연간 결제",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "가장 인기",
"basic": {
"name": "Basic",
"desc": "Momento의 마법을 경험하세요.",
"cta": "시작하기",
"feature0": "최대 100개 노트",
"feature1": "3개 노트북",
"feature2": "AI 크레딧 50 (평생)",
"feature3": "시맨틱 검색",
"feature4": "7일 기록"
},
"pro": {
"name": "Pro",
"desc": "까다로운 컨설턴트와 크리에이터를 위해.",
"cta": "Pro로 업그레이드",
"feature0": "무제한 노트",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "시맨틱 검색 200회",
"feature3": "에이전트 (월 12회)",
"feature4": "30일 기록",
"feature5": "이메일 지원"
},
"business": {
"name": "Business",
"desc": "팀과 프로덕트 매니저를 위해.",
"cta": "Business 선택",
"feature0": "10명 협업자 포함",
"feature1": "BYOK (13개 프로바이더)",
"feature2": "시맨틱 검색 1000회",
"feature3": "에이전트 (월 60회)",
"feature4": "무제한 브레인스토밍",
"feature5": "API 액세스"
},
"enterprise": {
"name": "Enterprise",
"desc": "안전한 조직 메모리.",
"cta": "영업 문의",
"feature0": "Business 전체",
"feature1": "무제한 에이전트",
"feature2": "SSO / SAML",
"feature3": "감사 로그 및 SLA",
"feature4": "전담 지원",
"feature5": "라이브 온보딩"
}
},
"byok": {
"label": "오픈 클라우드 기술",
"title": "BYOK 전략",
"desc": "OpenAI, Anthropic, Google API 키가 있으신가요? Momento에 직접 연결하세요. 강제 크레딧 한도 없이, 선호하는 프로바이더의 실제 사용량만 지불합니다.",
"noLockin": "락인 없음",
"noLockinDesc": "클릭 한 번으로 프로바이더 변경.",
"cost": "최적화된 비용",
"costDesc": "API 직접 가격으로 지불.",
"configLabel": "멀티 프로바이더 설정"
},
"cta": {
"title1": "당신의",
"title2": "잠재력을 깨울 준비가 되셨나요?",
"desc": "Momento로 미래를 만들고 있는 수천 명의 연구자, 디자이너, 사상가와 함께하세요.",
"button": "Momento 실행"
},
"footer": {
"desc": "AI로 증폭된 제2의 뇌. 창의적인 분들을 위해.",
"product": {
"title": "제품",
"link0": "변경 이력",
"link1": "문서",
"link2": "로드맵",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "커뮤니티",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "법적 고지",
"link0": "개인정보",
"link1": "이용약관",
"link2": "쿠키 정책",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -890,7 +890,7 @@
"recentNotesUpdateFailed": "Recente notities-instelling bijwerken mislukt"
},
"aiSettings": {
"title": "AI-instellingen",
"title": "AI",
"description": "Configureer uw AI-aangedreven functies en voorkeuren",
"features": "AI-functies",
"provider": "AI-provider",
@@ -917,7 +917,8 @@
"autoLabeling": "Labelsuggesties",
"autoLabelingDesc": "Stelt automatisch labels voor en past deze toe op uw notities",
"noteHistory": "Let op de geschiedenis",
"noteHistoryDesc": "Schakel momentopnamen van versies en herstel vanuit de geschiedenis in"
"noteHistoryDesc": "Schakel momentopnamen van versies en herstel vanuit de geschiedenis in",
"titleSuggestions": "Titelsuggesties"
},
"general": {
"loading": "Laden...",
@@ -1115,7 +1116,13 @@
"languageDetection": "Taaldetectie",
"languageDetectionDesc": "Detecteert automatisch de taal van elke notitie",
"autoLabeling": "Automatisch labelen",
"autoLabelingDesc": "Stelt labels voor en past ze automatisch toe"
"autoLabelingDesc": "Stelt labels voor en past ze automatisch toe",
"fallbackSectionTitle": "Fallback-provider (optioneel)",
"fallbackSectionDescription": "Wordt automatisch gebruikt bij providerfouten (429, 5xx). Eén nieuwe poging binnen 1,5 s.",
"fallbackProvider": "Fallback-provider",
"fallbackModel": "Fallback-model",
"fallbackNone": "Geen (uitgeschakeld)",
"fallbackModelPlaceholder": "bijv. gpt-4o-mini"
},
"resend": {
"title": "Resend (Aanbevolen)",
@@ -1173,6 +1180,8 @@
"deleteFailed": "Verwijderen mislukt",
"roleUpdateSuccess": "Gebruikersrol bijgewerkt naar {role}",
"roleUpdateFailed": "Rol bijwerken mislukt",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "Degraderen",
"promote": "Bevorderen",
"confirmDelete": "Weet u zeker dat u deze gebruiker wilt verwijderen?",
@@ -1180,6 +1189,7 @@
"name": "Naam",
"email": "E-mail",
"role": "Rol",
"subscription": "Subscription",
"createdAt": "Aangemaakt op",
"actions": "Acties"
},
@@ -1371,7 +1381,7 @@
"loading": "Laden..."
},
"dataManagement": {
"title": "Gegevensbeheer",
"title": "Data",
"toolsDescription": "Hulpmiddelen om de gezondheid van uw database te behouden",
"exporting": "Exporteren...",
"importing": "Importeren...",
@@ -1436,7 +1446,7 @@
"fontJetBrainsMono": "JetBrains Mono"
},
"generalSettings": {
"title": "Algemene instellingen",
"title": "General",
"description": "Algemene applicatie-instellingen"
},
"toast": {
@@ -1622,7 +1632,7 @@
"collapse": "Inklappen"
},
"mcpSettings": {
"title": "MCP-instellingen",
"title": "MCP",
"description": "Beheer uw API-sleutels en configureer externe tools",
"whatIsMcp": {
"title": "Wat is MCP?",
@@ -2211,7 +2221,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "De sessiehost heeft zijn AI-limiet bereikt. Vraag om een upgrade van het abonnement.",
"quotaHost": "Je hebt je AI-limiet voor deze brainstorm bereikt. Upgrade je abonnement om door te gaan."
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2323,6 +2335,215 @@
"checkoutSuccessBody": "Welkom bij {tier}. Je functies zijn nu ontgrendeld.",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"currentUsage": "Huidig gebruik",
"currentPeriod": "Huidige periode",
"aiCredits": "AI-credits",
"used": "gebruikt",
"billing": "Facturatie",
"renewal": "Verlenging",
"paidPlanDesc": "Uw abonnement wordt automatisch verlengd.",
"businessDescription": "Voor teams en productmanagers."
},
"landing": {
"nav": {
"features": "Functies",
"agents": "AI-agents",
"brainstorm": "Brainstorm",
"pricing": "Prijzen",
"tech": "Architectuur",
"login": "Inloggen",
"cta": "Aan de slag"
},
"hero": {
"badge": "Aangedreven door kunstmatige intelligentie",
"title1": "Uw tweede brein,",
"title2": "eindelijk versterkt.",
"subtitle": "Momento is meer dan een notitie-app. Het is een intelligent ecosysteem dat uw ideeën in realtime verbindt, analyseert en ontwikkelt met 6 soorten AI-agents en geavanceerde semantische zoekfunctie.",
"cta": "Nu registreren",
"secondary": "Bekijk functies",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"Verbinding gedetecteerd met uw duurzaam designproject van maart 2024...\"",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12 ideeën gegenereerd"
},
"features": {
"label": "AI-mogelijkheden",
"title": "Vloeiende intelligentie,",
"title2": "verweven in elk woord.",
"desc": "Momento orkestreert uw ideeën via een multi-provider architectuur.",
"f1Title": "Semantisch zoeken",
"f1Desc": "Stop met zoeken op trefwoorden. Vind op concept. Onze hybride Vector + FTS-engine begrijpt de intentie achter uw notities.",
"f2Title": "Contextuele RAG-chat",
"f2Desc": "Praat met uw kennis. Onze agents lezen uw notities, verkennen het web en analyseren documenten voor nauwkeurige antwoorden.",
"f3Title": "Augmented schrijven",
"f3Desc": "Herschrijven, titelsuggesties, automatisch taggen en samenvattingen. AI structureert uw denken op de achtergrond."
},
"agents": {
"label": "Gespecialiseerde agents",
"title": "Delegeer complex werk.",
"desc": "6 soorten autonome AI-agents voor onderzoek, samenvattingen en presentaties.",
"scraper": {
"title": "Scraper",
"desc": "Scrapet URL's, parseert RSS-feeds en synthetiseert info met slimme beeldplaatsing."
},
"researcher": {
"title": "Researcher",
"desc": "Genereert complexe queries, verkent webbronnen en schrijft gestructureerde onderzoeksnotities."
},
"slideGen": {
"title": "Slide Gen",
"desc": "Zet uw notities om in professionele PowerPoint-presentaties of interactieve HTML-slides."
},
"monitor": {
"title": "Monitor",
"desc": "Analyseert continu uw notitieboeken om trends en nieuwe inzichten te detecteren."
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "Zet ideeën om in vloeiende Excalidraw-diagrammen (mindmaps, flowcharts) met auto-layout."
},
"custom": {
"title": "Custom",
"desc": "Definieer eigen agents met specifieke rollen en databronnen."
}
},
"brainstorm": {
"label": "Gedachtegolven",
"title": "Radiale brainstorming in realtime.",
"waveGeneration": {
"title": "Golfgeneratie",
"desc": "Variaties, analogieën, dan disrupties. AI duwt uw startconcept tot het uiterste."
},
"collaboration": {
"title": "Native samenwerking",
"desc": "AI-spookcursors, gesynchroniseerde avatars en realtime knooppuntbeweging."
},
"export": {
"title": "Semantische export",
"desc": "Zet uw hele brainstorm om in gestructureerde notities met één klik."
},
"disruptionLabel": "DISRUPTIE",
"disruptionText": "Modulaire architectuur 2.0",
"analogyLabel": "ANALOGIE",
"analogyText": "Het getijdenritme"
},
"tech": {
"label": "Architectuur en providers",
"title": "Koppel uw eigen AI-model.",
"tags": {
"title": "Tags",
"desc": "Onafhankelijk configureerbaar met elk model."
},
"embeddings": {
"title": "Embeddings",
"desc": "Onafhankelijk configureerbaar met elk model."
},
"chatRag": {
"title": "Chat RAG",
"desc": "Onafhankelijk configureerbaar met elk model."
}
},
"pricing": {
"label": "Plannen en prijzen",
"title": "Kies uw versterkingsniveau.",
"desc": "Flexibele opties voor creatieve geesten, van individueel gebruik tot grote organisaties.",
"monthly": "Maandelijks",
"annual": "Jaarlijks",
"perMonth": "/maand",
"perMonthAnnual": "/maand, jaarlijks gefactureerd",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "Meest populair",
"basic": {
"name": "Basic",
"desc": "Ontdek de magie van Momento.",
"cta": "Starten",
"feature0": "Max. 100 notities",
"feature1": "3 notitieboeken",
"feature2": "50 AI-credits (levenslang)",
"feature3": "Semantisch zoeken",
"feature4": "7 dagen geschiedenis"
},
"pro": {
"name": "Pro",
"desc": "Voor veeleisende consultants en makers.",
"cta": "Upgrade naar Pro",
"feature0": "Onbeperkte notities",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "200 semantische zoekopdrachten",
"feature3": "Agents (12 runs/maand)",
"feature4": "30 dagen geschiedenis",
"feature5": "E-mailondersteuning"
},
"business": {
"name": "Business",
"desc": "Voor teams en productmanagers.",
"cta": "Kies Business",
"feature0": "10 medewerkers inbegrepen",
"feature1": "BYOK (13 providers)",
"feature2": "1000 semantische zoekopdrachten",
"feature3": "Agents (60 runs/maand)",
"feature4": "Onbeperkt brainstormen",
"feature5": "API-toegang"
},
"enterprise": {
"name": "Enterprise",
"desc": "Veilig organisatiegeheugen.",
"cta": "Contact verkoop",
"feature0": "Alles uit Business",
"feature1": "Onbeperkte agents",
"feature2": "SSO / SAML",
"feature3": "Audit Logs en SLA",
"feature4": "Dedicated support",
"feature5": "Live onboarding"
}
},
"byok": {
"label": "Open cloudtechnologie",
"title": "De BYOK-strategie",
"desc": "Heeft u al API-sleutels van OpenAI, Anthropic of Google? Koppel ze direct aan Momento. Gebruik AI zonder opgelegde creditlimieten en betaal alleen wat u daadwerkelijk verbruikt bij uw favoriete provider.",
"noLockin": "Geen lock-in",
"noLockinDesc": "Wissel provider in 1 klik.",
"cost": "Geoptimaliseerde kosten",
"costDesc": "Betaal de directe API-prijs.",
"configLabel": "Multi-provider config"
},
"cta": {
"title1": "Klaar om uw",
"title2": "volledige potentieel te ontgrendelen?",
"desc": "Sluit u aan bij duizenden onderzoekers, ontwerpers en denkers die Momento al gebruiken om hun toekomst te bouwen.",
"button": "Momento starten"
},
"footer": {
"desc": "Het AI-versterkte tweede brein. Ontworpen voor creatieve geesten.",
"product": {
"title": "Product",
"link0": "Changelog",
"link1": "Documentatie",
"link2": "Roadmap",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "Community",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "Juridisch",
"link0": "Privacybeleid",
"link1": "Servicevoorwaarden",
"link2": "Cookiebeleid",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -890,7 +890,7 @@
"recentNotesUpdateFailed": "Nie udało się zaktualizować ustawienia ostatnich notatek"
},
"aiSettings": {
"title": "Ustawienia AI",
"title": "AI",
"description": "Skonfiguruj swoje funkcje AI i preferencje",
"features": "Funkcje AI",
"provider": "Dostawca AI",
@@ -917,7 +917,8 @@
"autoLabeling": "Sugestie dotyczące etykiet",
"autoLabelingDesc": "Automatycznie sugeruje i stosuje etykiety do notatek",
"noteHistory": "Uwaga na historię",
"noteHistoryDesc": "Włącz migawki wersji i przywracanie z Historii"
"noteHistoryDesc": "Włącz migawki wersji i przywracanie z Historii",
"titleSuggestions": "Sugestie tytułów"
},
"general": {
"loading": "Ładowanie...",
@@ -1115,7 +1116,13 @@
"languageDetection": "Wykrywanie języka",
"languageDetectionDesc": "Automatycznie wykrywa język każdej notatki",
"autoLabeling": "Automatyczne etykietowanie",
"autoLabelingDesc": "Automatycznie sugeruje i stosuje etykiety"
"autoLabelingDesc": "Automatycznie sugeruje i stosuje etykiety",
"fallbackSectionTitle": "Zapasowy dostawca (opcjonalnie)",
"fallbackSectionDescription": "Używany automatycznie przy błędach dostawcy (429, 5xx). Jedna ponowna próba w 1,5 s.",
"fallbackProvider": "Zapasowy dostawca",
"fallbackModel": "Zapasowy model",
"fallbackNone": "Brak (wyłączone)",
"fallbackModelPlaceholder": "np. gpt-4o-mini"
},
"resend": {
"title": "Resend (Zalecane)",
@@ -1173,6 +1180,8 @@
"deleteFailed": "Nie udało się usunąć",
"roleUpdateSuccess": "Rola użytkownika zmieniona na {role}",
"roleUpdateFailed": "Nie udało się zaktualizować roli",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "Zdegraduj",
"promote": "Awansuj",
"confirmDelete": "Czy na pewno chcesz usunąć tego użytkownika?",
@@ -1180,6 +1189,7 @@
"name": "Imię",
"email": "E-mail",
"role": "Rola",
"subscription": "Subscription",
"createdAt": "Utworzono",
"actions": "Akcje"
},
@@ -1371,7 +1381,7 @@
"loading": "Ładowanie..."
},
"dataManagement": {
"title": "Zarządzanie danymi",
"title": "Data",
"toolsDescription": "Narzędzia do utrzymania kondycji bazy danych",
"exporting": "Eksportowanie...",
"importing": "Importowanie...",
@@ -1436,7 +1446,7 @@
"fontJetBrainsMono": "JetBrains Mono"
},
"generalSettings": {
"title": "Ustawienia ogólne",
"title": "General",
"description": "Ogólne ustawienia aplikacji"
},
"toast": {
@@ -1622,7 +1632,7 @@
"collapse": "Zwiń"
},
"mcpSettings": {
"title": "Ustawienia MCP",
"title": "MCP",
"description": "Zarządzaj kluczami API i konfiguruj narzędzia zewnętrzne",
"whatIsMcp": {
"title": "Czym jest MCP?",
@@ -2211,7 +2221,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "Gospodarz sesji wyczerpał limit AI. Poproś go o ulepszenie planu.",
"quotaHost": "Osiągnąłeś limit AI dla tego brainstormu. Ulepsz plan, aby kontynuować."
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2323,6 +2335,215 @@
"checkoutSuccessBody": "Witamy w {tier}. Twoje funkcje są teraz odblokowane.",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"currentUsage": "Bieżące użycie",
"currentPeriod": "Bieżący okres",
"aiCredits": "Kredyty AI",
"used": "użyte",
"billing": "Rozliczenia",
"renewal": "Odnowienie",
"paidPlanDesc": "Twoja subskrypcja odnawia się automatycznie.",
"businessDescription": "Dla zespołów i kierowników produktu."
},
"landing": {
"nav": {
"features": "Funkcje",
"agents": "Agenci AI",
"brainstorm": "Brainstorm",
"pricing": "Cennik",
"tech": "Architektura",
"login": "Zaloguj się",
"cta": "Rozpocznij"
},
"hero": {
"badge": "Napędzane sztuczną inteligencją",
"title1": "Twój drugi mózg,",
"title2": "wreszcie wzmocniony.",
"subtitle": "Momento to coś więcej niż aplikacja do notatek. To inteligentny ekosystem, który łączy, analizuje i rozwija Twoje pomysły w czasie rzeczywistym dzięki 6 typom agentów AI i zaawansowanemu wyszukiwaniu semantycznemu.",
"cta": "Zarejestruj się teraz",
"secondary": "Zobacz funkcje",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"Wykryto powiązanie z Twoim projektem zrównoważonego designu z marca 2024...\"",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12 wygenerowanych pomysłów"
},
"features": {
"label": "Możliwości AI",
"title": "Płynna inteligencja,",
"title2": "wpleciona w każde słowo.",
"desc": "Momento orkiestruje Twoje pomysły dzięki architekturze multi-provider.",
"f1Title": "Wyszukiwanie semantyczne",
"f1Desc": "Koniec z wyszukiwaniem po słowach kluczowych. Szukaj po pojęciu. Nasz hybrydowy silnik Vector + FTS rozumie intencję za Twoimi notatkami.",
"f2Title": "Kontekstowy czat RAG",
"f2Desc": "Rozmawiaj ze swoją wiedzą. Nasi agenci czytają notatki, eksplorują sieć i analizują dokumenty, by odpowiadać precyzyjnie.",
"f3Title": "Wzmocnione pisanie",
"f3Desc": "Przeformułowania, sugestie tytułów, automatyczne tagowanie i podsumowania. AI porządkuje Twoje myślenie w tle."
},
"agents": {
"label": "Wyspecjalizowani agenci",
"title": "Deleguj złożoną pracę.",
"desc": "6 typów autonomicznych agentów AI do automatyzacji badań, streszczeń i prezentacji.",
"scraper": {
"title": "Scraper",
"desc": "Pobiera URL-e, parsuje kanały RSS i syntetyzuje informacje z inteligentnym układem obrazów."
},
"researcher": {
"title": "Researcher",
"desc": "Generuje złożone zapytania, eksploruje źródła web i pisze ustrukturyzowane notatki badawcze."
},
"slideGen": {
"title": "Slide Gen",
"desc": "Zamienia notatki w profesjonalne prezentacje PowerPoint lub interaktywne slajdy HTML."
},
"monitor": {
"title": "Monitor",
"desc": "Ciągle analizuje zeszyty, by wykrywać trendy i nowe spostrzeżenia."
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "Zamienia pomysły w płynne diagramy Excalidraw (mapy myśli, schematy) z auto-layout."
},
"custom": {
"title": "Custom",
"desc": "Zdefiniuj własnych agentów z określonymi rolami i źródłami danych."
}
},
"brainstorm": {
"label": "Fale myśli",
"title": "Radialny brainstorming w czasie rzeczywistym.",
"waveGeneration": {
"title": "Generacja falowa",
"desc": "Wariacje, analogie, potem dysrupcje. AI popycha początkowy koncept do granic możliwości."
},
"collaboration": {
"title": "Natywna współpraca",
"desc": "Duchowe kursory AI, zsynchronizowane awatary i ruch węzłów w czasie rzeczywistym."
},
"export": {
"title": "Eksport semantyczny",
"desc": "Zamień cały brainstorming w ustrukturyzowane notatki jednym kliknięciem."
},
"disruptionLabel": "DYSRUPCJA",
"disruptionText": "Architektura modułowa 2.0",
"analogyLabel": "ANALOGIA",
"analogyText": "Cykl pływów"
},
"tech": {
"label": "Architektura i dostawcy",
"title": "Podłącz własny model AI.",
"tags": {
"title": "Tagi",
"desc": "Niezależnie konfigurowalne z dowolnym modelem."
},
"embeddings": {
"title": "Embeddings",
"desc": "Niezależnie konfigurowalne z dowolnym modelem."
},
"chatRag": {
"title": "Chat RAG",
"desc": "Niezależnie konfigurowalne z dowolnym modelem."
}
},
"pricing": {
"label": "Plany i ceny",
"title": "Wybierz poziom wzmocnienia.",
"desc": "Elastyczne opcje dla kreatywnych umysłów — od użytku indywidualnego po duże organizacje.",
"monthly": "Miesięcznie",
"annual": "Rocznie",
"perMonth": "/mies.",
"perMonthAnnual": "/mies., rozliczane rocznie",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "Najpopularniejszy",
"basic": {
"name": "Basic",
"desc": "Odkryj magię Momento.",
"cta": "Zacznij",
"feature0": "Maks. 100 notatek",
"feature1": "3 zeszyty",
"feature2": "50 kredytów AI (dożywotnio)",
"feature3": "Wyszukiwanie semantyczne",
"feature4": "Historia 7 dni"
},
"pro": {
"name": "Pro",
"desc": "Dla wymagających konsultantów i twórców.",
"cta": "Przejdź na Pro",
"feature0": "Nieograniczone notatki",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "200 wyszukiwań semantycznych",
"feature3": "Agenci (12 uruchomień/mies.)",
"feature4": "Historia 30 dni",
"feature5": "Wsparcie e-mail"
},
"business": {
"name": "Business",
"desc": "Dla zespołów i product managerów.",
"cta": "Wybierz Business",
"feature0": "10 współpracowników w cenie",
"feature1": "BYOK (13 dostawców)",
"feature2": "1000 wyszukiwań semantycznych",
"feature3": "Agenci (60 uruchomień/mies.)",
"feature4": "Nieograniczony brainstorm",
"feature5": "Dostęp API"
},
"enterprise": {
"name": "Enterprise",
"desc": "Bezpieczna pamięć organizacyjna.",
"cta": "Kontakt ze sprzedażą",
"feature0": "Wszystko z Business",
"feature1": "Nieograniczeni agenci",
"feature2": "SSO / SAML",
"feature3": "Audit Logs i SLA",
"feature4": "Dedykowane wsparcie",
"feature5": "Onboarding na żywo"
}
},
"byok": {
"label": "Otwarta technologia chmurowa",
"title": "Strategia BYOK",
"desc": "Masz już klucze API OpenAI, Anthropic lub Google? Podłącz je bezpośrednio do Momento. Korzystaj z AI bez narzuconych limitów kredytów, płacąc tylko za faktyczne zużycie u ulubionego dostawcy.",
"noLockin": "Bez lock-in",
"noLockinDesc": "Zmień dostawcę jednym kliknięciem.",
"cost": "Zoptymalizowane koszty",
"costDesc": "Płać bezpośrednią cenę API.",
"configLabel": "Konfiguracja multi-provider"
},
"cta": {
"title1": "Gotowy, by uwolnić swój",
"title2": "pełny potencjał?",
"desc": "Dołącz do tysięcy badaczy, designerów i myślicieli, którzy już budują przyszłość z Momento.",
"button": "Uruchom Momento"
},
"footer": {
"desc": "Drugie mózg wzmocnione przez AI. Stworzone dla kreatywnych umysłów.",
"product": {
"title": "Produkt",
"link0": "Changelog",
"link1": "Dokumentacja",
"link2": "Roadmapa",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "Społeczność",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "Prawne",
"link0": "Polityka prywatności",
"link1": "Regulamin",
"link2": "Polityka cookies",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -890,7 +890,7 @@
"recentNotesUpdateFailed": "Falha ao atualizar configuração de notas recentes"
},
"aiSettings": {
"title": "Configurações de IA",
"title": "AI",
"description": "Configure seus recursos e preferências com IA",
"features": "Recursos de IA",
"provider": "Provedor de IA",
@@ -917,7 +917,8 @@
"autoLabeling": "Sugestões de rótulos",
"autoLabelingDesc": "Sugere e aplica rótulos automaticamente às suas notas",
"noteHistory": "Histórico de notas",
"noteHistoryDesc": "Habilite snapshots de versão e restauração do histórico"
"noteHistoryDesc": "Habilite snapshots de versão e restauração do histórico",
"titleSuggestions": "Sugestão de títulos"
},
"general": {
"loading": "Carregando...",
@@ -1115,7 +1116,13 @@
"languageDetection": "Detecção de idioma",
"languageDetectionDesc": "Detecta automaticamente o idioma de cada nota",
"autoLabeling": "Rotulagem automática",
"autoLabelingDesc": "Sugere e aplica rótulos automaticamente"
"autoLabelingDesc": "Sugere e aplica rótulos automaticamente",
"fallbackSectionTitle": "Provedor de contingência (opcional)",
"fallbackSectionDescription": "Usado automaticamente em erros do provedor (429, 5xx). Uma nova tentativa em 1,5 s.",
"fallbackProvider": "Provedor de contingência",
"fallbackModel": "Modelo de contingência",
"fallbackNone": "Nenhum (desativado)",
"fallbackModelPlaceholder": "ex.: gpt-4o-mini"
},
"resend": {
"title": "Resend (Recomendado)",
@@ -1173,6 +1180,8 @@
"deleteFailed": "Falha ao excluir",
"roleUpdateSuccess": "Função do usuário atualizada para {role}",
"roleUpdateFailed": "Falha ao atualizar função",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "Rebaixar",
"promote": "Promover",
"confirmDelete": "Tem certeza de que deseja excluir este usuário?",
@@ -1180,6 +1189,7 @@
"name": "Nome",
"email": "E-mail",
"role": "Função",
"subscription": "Subscription",
"createdAt": "Criado em",
"actions": "Ações"
},
@@ -1371,7 +1381,7 @@
"loading": "Carregando..."
},
"dataManagement": {
"title": "Gerenciamento de Dados",
"title": "Data",
"toolsDescription": "Ferramentas para manter a saúde do seu banco de dados",
"exporting": "Exportando...",
"importing": "Importando...",
@@ -1436,7 +1446,7 @@
"fontJetBrainsMono": "JetBrains Mono"
},
"generalSettings": {
"title": "Configurações gerais",
"title": "General",
"description": "Configurações gerais do aplicativo"
},
"toast": {
@@ -1622,7 +1632,7 @@
"collapse": "Recolher"
},
"mcpSettings": {
"title": "Configurações MCP",
"title": "MCP",
"description": "Gerencie suas chaves API e configure ferramentas externas",
"whatIsMcp": {
"title": "O que é MCP?",
@@ -2211,7 +2221,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "O anfitrião da sessão atingiu o limite de IA. Peça-lhe para atualizar o plano.",
"quotaHost": "Atingiu o limite de IA deste brainstorm. Atualize o plano para continuar."
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2323,6 +2335,215 @@
"checkoutSuccessBody": "Bem-vindo ao {tier}. As suas funcionalidades estão agora desbloqueadas.",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"currentUsage": "Uso atual",
"currentPeriod": "Período atual",
"aiCredits": "Créditos IA",
"used": "usados",
"billing": "Faturação",
"renewal": "Renovação",
"paidPlanDesc": "Sua assinatura renova automaticamente.",
"businessDescription": "Para equipes e líderes de produto."
},
"landing": {
"nav": {
"features": "Funcionalidades",
"agents": "Agentes IA",
"brainstorm": "Brainstorm",
"pricing": "Preços",
"tech": "Arquitetura",
"login": "Entrar",
"cta": "Começar"
},
"hero": {
"badge": "Impulsionado por inteligência artificial",
"title1": "O seu segundo cérebro,",
"title2": "finalmente amplificado.",
"subtitle": "O Momento é mais do que uma app de notas. É um ecossistema inteligente que liga, analisa e desenvolve as suas ideias em tempo real com 6 tipos de agentes IA e pesquisa semântica de ponta.",
"cta": "Registe-se agora",
"secondary": "Ver funcionalidades",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"Ligação detetada ao seu projeto de design sustentável de março de 2024...\"",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12 ideias geradas"
},
"features": {
"label": "Capacidades IA",
"title": "Inteligência fluida,",
"title2": "entrelaçada em cada palavra.",
"desc": "O Momento orquestra as suas ideias através de uma arquitetura multi-fornecedor.",
"f1Title": "Pesquisa semântica",
"f1Desc": "Deixe de pesquisar por palavras-chave. Encontre por conceito. O nosso motor híbrido Vector + FTS compreende a intenção por trás das suas notas.",
"f2Title": "Chat RAG contextual",
"f2Desc": "Converse com o seu conhecimento. Os nossos agentes leem as suas notas, exploram a web e analisam documentos para responder com precisão.",
"f3Title": "Escrita aumentada",
"f3Desc": "Reformulação, sugestões de títulos, etiquetagem automática e resumos. A IA trabalha em segundo plano para estruturar o seu pensamento."
},
"agents": {
"label": "Agentes especializados",
"title": "Delegue o trabalho complexo.",
"desc": "6 tipos de agentes IA autónomos para automatizar pesquisa, resumos e apresentações.",
"scraper": {
"title": "Scraper",
"desc": "Extrai URLs, analisa feeds RSS e sintetiza informação com colocação inteligente de imagens."
},
"researcher": {
"title": "Researcher",
"desc": "Gera consultas complexas, explora fontes web e escreve notas de pesquisa estruturadas."
},
"slideGen": {
"title": "Slide Gen",
"desc": "Transforma as suas notas em apresentações PowerPoint profissionais ou slides HTML interativos."
},
"monitor": {
"title": "Monitor",
"desc": "Analisa continuamente os seus cadernos para detetar tendências e novos insights."
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "Converte ideias em diagramas Excalidraw fluidos (mapas mentais, fluxogramas) com auto-layout."
},
"custom": {
"title": "Custom",
"desc": "Defina os seus próprios agentes com papéis e fontes de dados específicos."
}
},
"brainstorm": {
"label": "Ondas de pensamento",
"title": "Brainstorming radial em tempo real.",
"waveGeneration": {
"title": "Geração por ondas",
"desc": "Variações, analogias e depois disrupções. A IA leva o seu conceito inicial aos limites."
},
"collaboration": {
"title": "Colaboração nativa",
"desc": "Cursores fantasma IA, avatares sincronizados e movimento de nós em tempo real."
},
"export": {
"title": "Exportação semântica",
"desc": "Converta todo o brainstorming em notas estruturadas com um clique."
},
"disruptionLabel": "DISRUPÇÃO",
"disruptionText": "Arquitetura modular 2.0",
"analogyLabel": "ANALOGIA",
"analogyText": "O ciclo das marés"
},
"tech": {
"label": "Arquitetura e fornecedores",
"title": "Ligue o seu próprio modelo de IA.",
"tags": {
"title": "Tags",
"desc": "Configurável de forma independente com qualquer modelo."
},
"embeddings": {
"title": "Embeddings",
"desc": "Configurável de forma independente com qualquer modelo."
},
"chatRag": {
"title": "Chat RAG",
"desc": "Configurável de forma independente com qualquer modelo."
}
},
"pricing": {
"label": "Planos e preços",
"title": "Escolha o seu nível de amplificação.",
"desc": "Opções flexíveis para mentes criativas, do uso individual a grandes organizações.",
"monthly": "Mensal",
"annual": "Anual",
"perMonth": "/mês",
"perMonthAnnual": "/mês, faturado anualmente",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "Mais popular",
"basic": {
"name": "Basic",
"desc": "Descubra a magia do Momento.",
"cta": "Começar",
"feature0": "100 notas máx.",
"feature1": "3 cadernos",
"feature2": "50 créditos IA (vitalícios)",
"feature3": "Pesquisa semântica",
"feature4": "Histórico 7 dias"
},
"pro": {
"name": "Pro",
"desc": "Para consultores e criadores exigentes.",
"cta": "Upgrade para Pro",
"feature0": "Notas ilimitadas",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "200 pesquisas semânticas",
"feature3": "Agentes (12 execuções/mês)",
"feature4": "Histórico 30 dias",
"feature5": "Suporte por email"
},
"business": {
"name": "Business",
"desc": "Para equipas e product managers.",
"cta": "Escolher Business",
"feature0": "10 colaboradores incluídos",
"feature1": "BYOK (13 fornecedores)",
"feature2": "1000 pesquisas semânticas",
"feature3": "Agentes (60 execuções/mês)",
"feature4": "Brainstorm ilimitado",
"feature5": "Acesso API"
},
"enterprise": {
"name": "Enterprise",
"desc": "Memória organizacional segura.",
"cta": "Contactar vendas",
"feature0": "Tudo do Business",
"feature1": "Agentes ilimitados",
"feature2": "SSO / SAML",
"feature3": "Audit Logs e SLA",
"feature4": "Suporte dedicado",
"feature5": "Onboarding ao vivo"
}
},
"byok": {
"label": "Tecnologia cloud aberta",
"title": "A estratégia BYOK",
"desc": "Já tem chaves API OpenAI, Anthropic ou Google? Ligue-as diretamente ao Momento. Use IA sem limites de crédito impostos, pagando apenas o que consome no seu fornecedor favorito.",
"noLockin": "Sem lock-in",
"noLockinDesc": "Mude de fornecedor em 1 clique.",
"cost": "Custos otimizados",
"costDesc": "Pague o preço direto da API.",
"configLabel": "Config multi-fornecedor"
},
"cta": {
"title1": "Pronto para libertar o seu",
"title2": "pleno potencial?",
"desc": "Junte-se a milhares de investigadores, designers e pensadores que já usam o Momento para construir o futuro.",
"button": "Lançar Momento"
},
"footer": {
"desc": "O segundo cérebro amplificado por IA. Feito para mentes criativas.",
"product": {
"title": "Produto",
"link0": "Changelog",
"link1": "Documentação",
"link2": "Roadmap",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "Comunidade",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "Legal",
"link0": "Privacidade",
"link1": "Termos de serviço",
"link2": "Cookies",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -890,7 +890,7 @@
"recentNotesUpdateFailed": "Не удалось обновить настройку недавних заметок"
},
"aiSettings": {
"title": "Настройки ИИ",
"title": "AI",
"description": "Настройте функции и предпочтения на базе ИИ",
"features": "Функции ИИ",
"provider": "Провайдер ИИ",
@@ -917,7 +917,8 @@
"autoLabeling": "Предложения по ярлыкам",
"autoLabelingDesc": "Автоматически предлагает и применяет ярлыки к вашим заметкам.",
"noteHistory": "История заметок",
"noteHistoryDesc": "Включить снимки версий и восстановление из истории"
"noteHistoryDesc": "Включить снимки версий и восстановление из истории",
"titleSuggestions": "Предложения заголовков"
},
"general": {
"loading": "Загрузка...",
@@ -1115,7 +1116,13 @@
"languageDetection": "Определение языка",
"languageDetectionDesc": "Автоопределение языка каждой заметки",
"autoLabeling": "Автомаркировка",
"autoLabelingDesc": "Автопредложение и применение меток"
"autoLabelingDesc": "Автопредложение и применение меток",
"fallbackSectionTitle": "Резервный провайдер (необязательно)",
"fallbackSectionDescription": "Используется автоматически при ошибках провайдера (429, 5xx). Одна повторная попытка за 1,5 с.",
"fallbackProvider": "Резервный провайдер",
"fallbackModel": "Резервная модель",
"fallbackNone": "Нет (отключено)",
"fallbackModelPlaceholder": "напр. gpt-4o-mini"
},
"resend": {
"title": "Resend (Рекомендуется)",
@@ -1173,6 +1180,8 @@
"deleteFailed": "Не удалось удалить",
"roleUpdateSuccess": "Роль пользователя обновлена на {role}",
"roleUpdateFailed": "Не удалось обновить роль",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "Понизить",
"promote": "Повысить",
"confirmDelete": "Вы уверены, что хотите удалить этого пользователя?",
@@ -1180,6 +1189,7 @@
"name": "Имя",
"email": "Эл. почта",
"role": "Роль",
"subscription": "Subscription",
"createdAt": "Дата создания",
"actions": "Действия"
},
@@ -1371,7 +1381,7 @@
"loading": "Загрузка..."
},
"dataManagement": {
"title": "Управление данными",
"title": "Data",
"toolsDescription": "Инструменты для поддержания базы данных в рабочем состоянии",
"exporting": "Экспорт...",
"importing": "Импорт...",
@@ -1436,7 +1446,7 @@
"fontJetBrainsMono": "JetBrains Mono"
},
"generalSettings": {
"title": "Общие настройки",
"title": "General",
"description": "Общие настройки приложения"
},
"toast": {
@@ -1622,7 +1632,7 @@
"collapse": "Свернуть"
},
"mcpSettings": {
"title": "Настройки MCP",
"title": "MCP",
"description": "Управление ключами API и настройка внешних инструментов",
"whatIsMcp": {
"title": "Что такое MCP?",
@@ -2211,7 +2221,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "Организатор сессии исчерпал лимит ИИ. Попросите его обновить тариф.",
"quotaHost": "Вы исчерпали лимит ИИ для этого мозгового штурма. Обновите тариф, чтобы продолжить."
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2323,6 +2335,215 @@
"checkoutSuccessBody": "Добро пожаловать в {tier}. Ваши функции теперь доступны.",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"currentUsage": "Текущее использование",
"currentPeriod": "Текущий период",
"aiCredits": "ИИ-кредиты",
"used": "использовано",
"billing": "Оплата",
"renewal": "Продление",
"paidPlanDesc": "Ваша подписка продлевается автоматически.",
"businessDescription": "Для команд и руководителей продуктов."
},
"landing": {
"nav": {
"features": "Возможности",
"agents": "ИИ-агенты",
"brainstorm": "Brainstorm",
"pricing": "Тарифы",
"tech": "Архитектура",
"login": "Войти",
"cta": "Начать"
},
"hero": {
"badge": "На базе искусственного интеллекта",
"title1": "Ваш второй мозг,",
"title2": "наконец усиленный.",
"subtitle": "Momento — это больше, чем приложение для заметок. Это интеллектуальная экосистема, которая связывает, анализирует и развивает ваши идеи в реальном времени с 6 типами ИИ-агентов и передовым семантическим поиском.",
"cta": "Зарегистрироваться",
"secondary": "Смотреть возможности",
"memoryEcho": "Memory Echo",
"memoryEchoText": "\"Обнаружена связь с вашим проектом устойчивого дизайна от марта 2024...\"",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12 идей сгенерировано"
},
"features": {
"label": "Возможности ИИ",
"title": "Плавный интеллект,",
"title2": "в каждом слове.",
"desc": "Momento управляет вашими идеями через мультипровайдерную архитектуру.",
"f1Title": "Семантический поиск",
"f1Desc": "Хватит искать по ключевым словам. Ищите по смыслу. Наш гибридный движок Vector + FTS понимает намерение за вашими заметками.",
"f2Title": "Контекстный RAG-чат",
"f2Desc": "Общайтесь со своими знаниями. Агенты читают заметки, исследуют веб и анализируют документы для точных ответов.",
"f3Title": "Усиленное письмо",
"f3Desc": "Переформулировка, предложения заголовков, автотеги и резюме. ИИ структурирует ваше мышление в фоне."
},
"agents": {
"label": "Специализированные агенты",
"title": "Делегируйте сложную работу.",
"desc": "6 типов автономных ИИ-агентов для автоматизации исследований, резюме и презентаций.",
"scraper": {
"title": "Scraper",
"desc": "Собирает URL, парсит RSS-ленты и синтезирует информацию с умным размещением изображений."
},
"researcher": {
"title": "Researcher",
"desc": "Генерирует сложные запросы, исследует веб-источники и пишет структурированные исследовательские заметки."
},
"slideGen": {
"title": "Slide Gen",
"desc": "Превращает заметки в профессиональные презентации PowerPoint или интерактивные HTML-слайды."
},
"monitor": {
"title": "Monitor",
"desc": "Непрерывно анализирует блокноты для выявления трендов и новых инсайтов."
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "Превращает идеи в плавные диаграммы Excalidraw (майндмэпы, блок-схемы) с авто-раскладкой."
},
"custom": {
"title": "Custom",
"desc": "Создавайте собственных агентов с нужными ролями и источниками данных."
}
},
"brainstorm": {
"label": "Волны мысли",
"title": "Радиальный мозговой штурм в реальном времени.",
"waveGeneration": {
"title": "Волновая генерация",
"desc": "Вариации, аналогии, затем дисрапции. ИИ доводит начальную концепцию до предела."
},
"collaboration": {
"title": "Нативная коллаборация",
"desc": "Призрачные курсоры ИИ, синхронизированные аватары и движение узлов в реальном времени."
},
"export": {
"title": "Семантический экспорт",
"desc": "Превратите весь мозговой штурм в структурированные заметки одним кликом."
},
"disruptionLabel": "ДИСРАПЦИЯ",
"disruptionText": "Модульная архитектура 2.0",
"analogyLabel": "АНАЛОГИЯ",
"analogyText": "Цикл приливов"
},
"tech": {
"label": "Архитектура и провайдеры",
"title": "Подключите свою модель ИИ.",
"tags": {
"title": "Теги",
"desc": "Независимо настраивается с любой моделью."
},
"embeddings": {
"title": "Embeddings",
"desc": "Независимо настраивается с любой моделью."
},
"chatRag": {
"title": "Chat RAG",
"desc": "Независимо настраивается с любой моделью."
}
},
"pricing": {
"label": "Тарифы и цены",
"title": "Выберите уровень усиления.",
"desc": "Гибкие варианты для творческих умов — от личного использования до крупных организаций.",
"monthly": "Ежемесячно",
"annual": "Ежегодно",
"perMonth": "/мес.",
"perMonthAnnual": "/мес., оплата раз в год",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "Самый популярный",
"basic": {
"name": "Basic",
"desc": "Откройте магию Momento.",
"cta": "Начать",
"feature0": "До 100 заметок",
"feature1": "3 блокнота",
"feature2": "50 ИИ-кредитов (навсегда)",
"feature3": "Семантический поиск",
"feature4": "История 7 дней"
},
"pro": {
"name": "Pro",
"desc": "Для требовательных консультантов и авторов.",
"cta": "Перейти на Pro",
"feature0": "Безлимитные заметки",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "200 семантических поисков",
"feature3": "Агенты (12 запусков/мес.)",
"feature4": "История 30 дней",
"feature5": "Поддержка по email"
},
"business": {
"name": "Business",
"desc": "Для команд и продакт-менеджеров.",
"cta": "Выбрать Business",
"feature0": "10 участников включено",
"feature1": "BYOK (13 провайдеров)",
"feature2": "1000 семантических поисков",
"feature3": "Агенты (60 запусков/мес.)",
"feature4": "Безлимитный brainstorm",
"feature5": "Доступ к API"
},
"enterprise": {
"name": "Enterprise",
"desc": "Безопасная организационная память.",
"cta": "Связаться с продажами",
"feature0": "Всё из Business",
"feature1": "Безлимитные агенты",
"feature2": "SSO / SAML",
"feature3": "Audit Logs и SLA",
"feature4": "Выделенная поддержка",
"feature5": "Живой onboarding"
}
},
"byok": {
"label": "Открытая облачная технология",
"title": "Стратегия BYOK",
"desc": "Уже есть API-ключи OpenAI, Anthropic или Google? Подключите их напрямую к Momento. Используйте ИИ без навязанных лимитов кредитов, платя только за фактическое потребление у любимого провайдера.",
"noLockin": "Без lock-in",
"noLockinDesc": "Смените провайдера в 1 клик.",
"cost": "Оптимизированные расходы",
"costDesc": "Платите прямую цену API.",
"configLabel": "Мультипровайдерная настройка"
},
"cta": {
"title1": "Готовы раскрыть свой",
"title2": "полный потенциал?",
"desc": "Присоединяйтесь к тысячам исследователей, дизайнеров и мыслителей, которые уже строят будущее с Momento.",
"button": "Запустить Momento"
},
"footer": {
"desc": "Второй мозг, усиленный ИИ. Создан для творческих умов.",
"product": {
"title": "Продукт",
"link0": "Changelog",
"link1": "Документация",
"link2": "Roadmap",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "Сообщество",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "Правовая информация",
"link0": "Конфиденциальность",
"link1": "Условия использования",
"link2": "Cookies",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

View File

@@ -890,7 +890,7 @@
"recentNotesUpdateFailed": "更新最近笔记设置失败"
},
"aiSettings": {
"title": "AI 设置",
"title": "AI",
"description": "配置您的 AI 驱动功能和偏好设置",
"features": "AI 功能",
"provider": "AI 提供商",
@@ -917,7 +917,8 @@
"autoLabeling": "标签建议",
"autoLabelingDesc": "自动建议标签并将其应用到您的笔记",
"noteHistory": "注释历史记录",
"noteHistoryDesc": "启用版本快照和从历史记录恢复"
"noteHistoryDesc": "启用版本快照和从历史记录恢复",
"titleSuggestions": "标题建议"
},
"general": {
"loading": "加载中...",
@@ -1115,7 +1116,13 @@
"languageDetection": "语言检测",
"languageDetectionDesc": "自动检测每条笔记的语言",
"autoLabeling": "自动标记",
"autoLabelingDesc": "自动建议并应用标签"
"autoLabelingDesc": "自动建议并应用标签",
"fallbackSectionTitle": "备用提供商(可选)",
"fallbackSectionDescription": "提供商出错时429、5xx自动启用。1.5 秒内重试一次。",
"fallbackProvider": "备用提供商",
"fallbackModel": "备用模型",
"fallbackNone": "无(已禁用)",
"fallbackModelPlaceholder": "例如 gpt-4o-mini"
},
"resend": {
"title": "Resend推荐",
@@ -1173,6 +1180,8 @@
"deleteFailed": "删除失败",
"roleUpdateSuccess": "用户角色已更新为 {role}",
"roleUpdateFailed": "更新角色失败",
"tierUpdateSuccess": "Subscription updated to {tier}",
"tierUpdateFailed": "Failed to update subscription",
"demote": "降级",
"promote": "升级",
"confirmDelete": "确定吗?此操作无法撤销。",
@@ -1180,6 +1189,7 @@
"name": "姓名",
"email": "邮箱",
"role": "角色",
"subscription": "Subscription",
"createdAt": "创建时间",
"actions": "操作"
},
@@ -1371,7 +1381,7 @@
"loading": "加载中..."
},
"dataManagement": {
"title": "数据管理",
"title": "Data",
"toolsDescription": "维护数据库健康的工具",
"exporting": "导出中...",
"importing": "导入中...",
@@ -1436,7 +1446,7 @@
"fontJetBrainsMono": "JetBrains Mono"
},
"generalSettings": {
"title": "常规设置",
"title": "General",
"description": "常规应用程序设置"
},
"toast": {
@@ -1622,7 +1632,7 @@
"collapse": "收起"
},
"mcpSettings": {
"title": "MCP 设置",
"title": "MCP",
"description": "管理 API 密钥并配置外部工具",
"whatIsMcp": {
"title": "什么是 MCP",
@@ -2211,7 +2221,9 @@
"exportDefaultNoteTitle": "Synthesis",
"exportOpening": "Opening…",
"ownerBadge": "Owner",
"waveBadge": "Wave {wave}"
"waveBadge": "Wave {wave}",
"quotaGuest": "会话主持人已达到 AI 额度上限。请让对方升级套餐。",
"quotaHost": "您已达到此头脑风暴的 AI 额度上限。升级套餐以继续。"
},
"usageMeter": {
"packName": "AI Discovery Pack",
@@ -2323,6 +2335,215 @@
"checkoutSuccessBody": "欢迎使用{tier},您的功能已解锁。",
"subscriptionType": "subscriptionType",
"renewalDate": "renewalDate",
"noRenewalDate": "—"
"noRenewalDate": "—",
"currentUsage": "当前使用量",
"currentPeriod": "当前周期",
"aiCredits": "AI 额度",
"used": "已使用",
"billing": "账单",
"renewal": "续订",
"paidPlanDesc": "您的订阅将自动续订。",
"businessDescription": "适合团队和产品负责人。"
},
"landing": {
"nav": {
"features": "功能",
"agents": "AI 智能体",
"brainstorm": "Brainstorm",
"pricing": "定价",
"tech": "架构",
"login": "登录",
"cta": "立即开始"
},
"hero": {
"badge": "由人工智能驱动",
"title1": "你的第二大脑,",
"title2": "终于获得放大。",
"subtitle": "Momento 不只是笔记应用。它是一个智能生态,通过 6 类 AI 智能体与前沿语义搜索,实时连接、分析并延展你的想法。",
"cta": "立即注册",
"secondary": "查看功能",
"memoryEcho": "Memory Echo",
"memoryEchoText": "「检测到与您 2024 年 3 月可持续设计项目的关联……」",
"brainstormLive": "Brainstorm Live",
"ideasGenerated": "+12 条创意已生成"
},
"features": {
"label": "AI 能力",
"title": "流畅的智能,",
"title2": "融入每一个字。",
"desc": "Momento 通过多提供商架构统筹你的想法。",
"f1Title": "语义搜索",
"f1Desc": "别再只靠关键词搜索。按概念查找。混合 Vector + FTS 引擎理解笔记背后的意图。",
"f2Title": "上下文 RAG 对话",
"f2Desc": "与你的知识对话。智能体阅读笔记、探索网络并分析文档,精准作答。",
"f3Title": "增强写作",
"f3Desc": "改写、标题建议、自动标签与摘要。AI 在后台帮你梳理思路。"
},
"agents": {
"label": "专业智能体",
"title": "把复杂工作交给它们。",
"desc": "6 类自主 AI 智能体,自动化研究、摘要与演示。",
"scraper": {
"title": "Scraper",
"desc": "抓取 URL、解析 RSS并以智能配图方式汇总信息。"
},
"researcher": {
"title": "Researcher",
"desc": "生成复杂查询、探索网络来源并撰写结构化研究笔记。"
},
"slideGen": {
"title": "Slide Gen",
"desc": "将笔记转为专业 PowerPoint 或交互式 HTML 幻灯片。"
},
"monitor": {
"title": "Monitor",
"desc": "持续分析笔记本,发现趋势与新洞察。"
},
"diagramGen": {
"title": "Diagram Gen",
"desc": "将想法转为流畅的 Excalidraw 图表(思维导图、流程图)并自动排版。"
},
"custom": {
"title": "Custom",
"desc": "自定义角色与数据源的专属智能体。"
}
},
"brainstorm": {
"label": "思维之波",
"title": "实时放射状头脑风暴。",
"waveGeneration": {
"title": "波浪式生成",
"desc": "变体、类比再到颠覆。AI 将初始概念推向极限。"
},
"collaboration": {
"title": "原生协作",
"desc": "AI 幽灵光标、同步头像与节点实时移动。"
},
"export": {
"title": "语义导出",
"desc": "一键将整个头脑风暴转为结构化笔记。"
},
"disruptionLabel": "颠覆",
"disruptionText": "模块化架构 2.0",
"analogyLabel": "类比",
"analogyText": "潮汐周期"
},
"tech": {
"label": "架构与提供商",
"title": "连接你自己的 AI 模型。",
"tags": {
"title": "Tags",
"desc": "可与任意模型独立配置。"
},
"embeddings": {
"title": "Embeddings",
"desc": "可与任意模型独立配置。"
},
"chatRag": {
"title": "Chat RAG",
"desc": "可与任意模型独立配置。"
}
},
"pricing": {
"label": "方案与定价",
"title": "选择你的放大级别。",
"desc": "为创意人士提供灵活选择,从个人使用到大型组织。",
"monthly": "月付",
"annual": "年付",
"perMonth": "/月",
"perMonthAnnual": "/月,按年计费",
"perUser": "+ 3.90€/user",
"perUserAnnual": "+ 2.90€/user, billed annually",
"popular": "最受欢迎",
"basic": {
"name": "Basic",
"desc": "发现 Momento 的魅力。",
"cta": "开始使用",
"feature0": "最多 100 条笔记",
"feature1": "3 个笔记本",
"feature2": "50 AI 积分(终身)",
"feature3": "语义搜索",
"feature4": "7 天历史"
},
"pro": {
"name": "Pro",
"desc": "为挑剔的顾问与创作者。",
"cta": "升级到 Pro",
"feature0": "无限笔记",
"feature1": "BYOK (OpenAI/Anthropic)",
"feature2": "200 次语义搜索",
"feature3": "智能体(每月 12 次)",
"feature4": "30 天历史",
"feature5": "邮件支持"
},
"business": {
"name": "Business",
"desc": "面向团队与产品经理。",
"cta": "选择 Business",
"feature0": "含 10 位协作者",
"feature1": "BYOK13 家提供商)",
"feature2": "1000 次语义搜索",
"feature3": "智能体(每月 60 次)",
"feature4": "无限头脑风暴",
"feature5": "API 访问"
},
"enterprise": {
"name": "Enterprise",
"desc": "安全的组织记忆。",
"cta": "联系销售",
"feature0": "Business 全部功能",
"feature1": "无限智能体",
"feature2": "SSO / SAML",
"feature3": "审计日志与 SLA",
"feature4": "专属支持",
"feature5": "现场入门指导"
}
},
"byok": {
"label": "开放云技术",
"title": "BYOK 策略",
"desc": "已有 OpenAI、Anthropic 或 Google 的 API 密钥?直接接入 Momento。无强制额度限制只按所选提供商的实际消耗付费。",
"noLockin": "无锁定",
"noLockinDesc": "一键切换提供商。",
"cost": "优化成本",
"costDesc": "按 API 直连价格付费。",
"configLabel": "多提供商配置"
},
"cta": {
"title1": "准备好释放",
"title2": "你的全部潜能了吗?",
"desc": "加入数千名研究者、设计师与思考者,用 Momento 构建未来。",
"button": "启动 Momento"
},
"footer": {
"desc": "AI 放大的第二大脑。为创意头脑而设计。",
"product": {
"title": "产品",
"link0": "更新日志",
"link1": "文档",
"link2": "路线图",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"community": {
"title": "社区",
"link0": "Discord",
"link1": "Twitter / X",
"link2": "LinkedIn",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
},
"legal": {
"title": "法律",
"link0": "隐私政策",
"link1": "服务条款",
"link2": "Cookie 政策",
"link0Href": "#",
"link1Href": "#",
"link2Href": "#"
}
}
}
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 355 KiB

View File

@@ -0,0 +1,292 @@
#!/usr/bin/env node
/**
* Merges missing i18n keys (admin fallback, brainstorm quota, landing page)
* into locale files. Contextual translations — not word-for-word.
*/
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const localesDir = path.join(__dirname, '../locales')
function deepMerge(target, source) {
for (const key of Object.keys(source)) {
const sv = source[key]
if (sv && typeof sv === 'object' && !Array.isArray(sv)) {
if (!target[key] || typeof target[key] !== 'object') target[key] = {}
deepMerge(target[key], sv)
} else {
target[key] = sv
}
}
return target
}
function flatten(obj, prefix = '') {
const result = {}
for (const [k, v] of Object.entries(obj)) {
const key = prefix ? `${prefix}.${k}` : k
if (v && typeof v === 'object' && !Array.isArray(v)) Object.assign(result, flatten(v, key))
else result[key] = v
}
return result
}
const adminAiFallback = {
de: {
fallbackSectionTitle: 'Ausweich-Anbieter (optional)',
fallbackSectionDescription:
'Wird bei Anbieterfehlern automatisch genutzt (429, 5xx). Ein erneuter Versuch innerhalb von 1,5 s.',
fallbackProvider: 'Ausweich-Anbieter',
fallbackModel: 'Ausweich-Modell',
fallbackNone: 'Keiner (deaktiviert)',
fallbackModelPlaceholder: 'z. B. gpt-4o-mini',
},
es: {
fallbackSectionTitle: 'Proveedor de respaldo (opcional)',
fallbackSectionDescription:
'Se usa automáticamente ante errores del proveedor (429, 5xx). Un reintento en 1,5 s.',
fallbackProvider: 'Proveedor de respaldo',
fallbackModel: 'Modelo de respaldo',
fallbackNone: 'Ninguno (desactivado)',
fallbackModelPlaceholder: 'p. ej. gpt-4o-mini',
},
it: {
fallbackSectionTitle: 'Provider di riserva (opzionale)',
fallbackSectionDescription:
'Usato automaticamente in caso di errori del provider (429, 5xx). Un solo nuovo tentativo entro 1,5 s.',
fallbackProvider: 'Provider di riserva',
fallbackModel: 'Modello di riserva',
fallbackNone: 'Nessuno (disattivato)',
fallbackModelPlaceholder: 'es. gpt-4o-mini',
},
pt: {
fallbackSectionTitle: 'Provedor de contingência (opcional)',
fallbackSectionDescription:
'Usado automaticamente em erros do provedor (429, 5xx). Uma nova tentativa em 1,5 s.',
fallbackProvider: 'Provedor de contingência',
fallbackModel: 'Modelo de contingência',
fallbackNone: 'Nenhum (desativado)',
fallbackModelPlaceholder: 'ex.: gpt-4o-mini',
},
nl: {
fallbackSectionTitle: 'Fallback-provider (optioneel)',
fallbackSectionDescription:
'Wordt automatisch gebruikt bij providerfouten (429, 5xx). Eén nieuwe poging binnen 1,5 s.',
fallbackProvider: 'Fallback-provider',
fallbackModel: 'Fallback-model',
fallbackNone: 'Geen (uitgeschakeld)',
fallbackModelPlaceholder: 'bijv. gpt-4o-mini',
},
pl: {
fallbackSectionTitle: 'Zapasowy dostawca (opcjonalnie)',
fallbackSectionDescription:
'Używany automatycznie przy błędach dostawcy (429, 5xx). Jedna ponowna próba w 1,5 s.',
fallbackProvider: 'Zapasowy dostawca',
fallbackModel: 'Zapasowy model',
fallbackNone: 'Brak (wyłączone)',
fallbackModelPlaceholder: 'np. gpt-4o-mini',
},
ru: {
fallbackSectionTitle: 'Резервный провайдер (необязательно)',
fallbackSectionDescription:
'Используется автоматически при ошибках провайдера (429, 5xx). Одна повторная попытка за 1,5 с.',
fallbackProvider: 'Резервный провайдер',
fallbackModel: 'Резервная модель',
fallbackNone: 'Нет (отключено)',
fallbackModelPlaceholder: 'напр. gpt-4o-mini',
},
ar: {
fallbackSectionTitle: 'مزود احتياطي (اختياري)',
fallbackSectionDescription:
'يُستخدم تلقائياً عند أخطاء المزود (429، 5xx). محاولة واحدة خلال 1,5 ثانية.',
fallbackProvider: 'مزود احتياطي',
fallbackModel: 'نموذج احتياطي',
fallbackNone: 'لا شيء (معطّل)',
fallbackModelPlaceholder: 'مثال: gpt-4o-mini',
},
fa: {
fallbackSectionTitle: 'ارائه‌دهنده پشتیبان (اختیاری)',
fallbackSectionDescription:
'در صورت خطای ارائه‌دهنده (429، 5xx) به‌صورت خودکار استفاده می‌شود. یک تلاش مجدد در ۱,۵ ثانیه.',
fallbackProvider: 'ارائه‌دهنده پشتیبان',
fallbackModel: 'مدل پشتیبان',
fallbackNone: 'هیچ (غیرفعال)',
fallbackModelPlaceholder: 'مثلاً gpt-4o-mini',
},
hi: {
fallbackSectionTitle: 'फ़ॉलबैक प्रदाता (वैकल्पिक)',
fallbackSectionDescription:
'प्रदाता त्रुटियों (429, 5xx) पर स्वतः उपयोग। 1.5 सेकंड में एक पुनः प्रयास।',
fallbackProvider: 'फ़ॉलबैक प्रदाता',
fallbackModel: 'फ़ॉलबैक मॉडल',
fallbackNone: 'कोई नहीं (अक्षम)',
fallbackModelPlaceholder: 'उदा. gpt-4o-mini',
},
ja: {
fallbackSectionTitle: 'フォールバックプロバイダー(任意)',
fallbackSectionDescription:
'プロバイダーエラー時429、5xxに自動使用。1.5秒以内に1回再試行。',
fallbackProvider: 'フォールバックプロバイダー',
fallbackModel: 'フォールバックモデル',
fallbackNone: 'なし(無効)',
fallbackModelPlaceholder: '例: gpt-4o-mini',
},
ko: {
fallbackSectionTitle: '대체 제공업체(선택)',
fallbackSectionDescription:
'제공업체 오류(429, 5xx) 시 자동 사용. 1.5초 이내 1회 재시도.',
fallbackProvider: '대체 제공업체',
fallbackModel: '대체 모델',
fallbackNone: '없음(비활성화)',
fallbackModelPlaceholder: '예: gpt-4o-mini',
},
zh: {
fallbackSectionTitle: '备用提供商(可选)',
fallbackSectionDescription: '提供商出错时429、5xx自动启用。1.5 秒内重试一次。',
fallbackProvider: '备用提供商',
fallbackModel: '备用模型',
fallbackNone: '无(已禁用)',
fallbackModelPlaceholder: '例如 gpt-4o-mini',
},
}
const brainstormQuota = {
de: {
quotaGuest:
'Der Gastgeber der Sitzung hat sein KI-Kontingent aufgebraucht. Bitte ihn, seinen Tarif zu erweitern.',
quotaHost:
'Sie haben Ihr KI-Kontingent für dieses Brainstorming erreicht. Wechseln Sie den Tarif, um fortzufahren.',
},
es: {
quotaGuest:
'El anfitrión de la sesión ha alcanzado su límite de IA. Pídele que mejore su plan.',
quotaHost:
'Has alcanzado tu límite de IA para este brainstorm. Mejora tu plan para continuar.',
},
it: {
quotaGuest:
"L'host della sessione ha raggiunto il limite IA. Chiedigli di aggiornare il piano.",
quotaHost:
'Hai raggiunto il limite IA per questo brainstorm. Passa a un piano superiore per continuare.',
},
pt: {
quotaGuest:
'O anfitrião da sessão atingiu o limite de IA. Peça-lhe para atualizar o plano.',
quotaHost:
'Atingiu o limite de IA deste brainstorm. Atualize o plano para continuar.',
},
nl: {
quotaGuest:
'De sessiehost heeft zijn AI-limiet bereikt. Vraag om een upgrade van het abonnement.',
quotaHost:
'Je hebt je AI-limiet voor deze brainstorm bereikt. Upgrade je abonnement om door te gaan.',
},
pl: {
quotaGuest:
'Gospodarz sesji wyczerpał limit AI. Poproś go o ulepszenie planu.',
quotaHost:
'Osiągnąłeś limit AI dla tego brainstormu. Ulepsz plan, aby kontynuować.',
},
ru: {
quotaGuest:
'Организатор сессии исчерпал лимит ИИ. Попросите его обновить тариф.',
quotaHost:
'Вы исчерпали лимит ИИ для этого мозгового штурма. Обновите тариф, чтобы продолжить.',
},
ar: {
quotaGuest:
'استنفد مضيف الجلسة حدّ الذكاء الاصطناعي. اطلب منه ترقية خطته.',
quotaHost: 'لقد وصلت إلى حدّ الذكاء الاصطناعي لهذه الجلسة. رقِّ خطتك للمتابعة.',
},
fa: {
quotaGuest:
'میزبان جلسه به سقف هوش مصنوعی رسیده. از او بخواهید طرحش را ارتقا دهد.',
quotaHost:
'به سقف هوش مصنوعی این طوفان فکری رسیدید. برای ادامه، طرح خود را ارتقا دهید.',
},
hi: {
quotaGuest:
'सत्र के होस्ट की AI सीमा समाप्त हो गई है। उनसे अपना प्लान अपग्रेड करने को कहें।',
quotaHost:
'इस ब्रेनस्टॉर्म के लिए आपकी AI सीमा समाप्त हो गई है। जारी रखने के लिए प्लान अपग्रेड करें।',
},
ja: {
quotaGuest:
'セッションのホストがAI利用上限に達しました。プランのアップグレードを依頼してください。',
quotaHost:
'このブレインストームのAI上限に達しました。続けるにはプランをアップグレードしてください。',
},
ko: {
quotaGuest: '세션 호스트의 AI 한도에 도달했습니다. 플랜 업그레이드를 요청하세요.',
quotaHost:
'이 브레인스토밍의 AI 한도에 도달했습니다. 계속하려면 플랜을 업그레이드하세요.',
},
zh: {
quotaGuest: '会话主持人已达到 AI 额度上限。请让对方升级套餐。',
quotaHost: '您已达到此头脑风暴的 AI 额度上限。升级套餐以继续。',
},
}
// Landing blocks — load from generated JSON (keeps this script maintainable)
const landingPatchesPath = path.join(__dirname, 'i18n-landing-patches.json')
if (!fs.existsSync(landingPatchesPath)) {
console.error('Missing i18n-landing-patches.json — run generate-landing-patches first')
process.exit(1)
}
const landingPatches = JSON.parse(fs.readFileSync(landingPatchesPath, 'utf8'))
const TARGET_LANGS = [
'ar',
'de',
'es',
'fa',
'hi',
'it',
'ja',
'ko',
'nl',
'pl',
'pt',
'ru',
'zh',
]
for (const lang of TARGET_LANGS) {
const filePath = path.join(localesDir, `${lang}.json`)
const data = JSON.parse(fs.readFileSync(filePath, 'utf8'))
if (adminAiFallback[lang]) {
if (!data.admin) data.admin = {}
if (!data.admin.ai) data.admin.ai = {}
Object.assign(data.admin.ai, adminAiFallback[lang])
}
if (brainstormQuota[lang]) {
if (!data.brainstorm) data.brainstorm = {}
Object.assign(data.brainstorm, brainstormQuota[lang])
}
if (landingPatches[lang]) {
if (!data.landing) data.landing = {}
deepMerge(data.landing, landingPatches[lang])
}
fs.writeFileSync(filePath, JSON.stringify(data, null, 2) + '\n', 'utf8')
console.log(`${lang}.json updated`)
}
// Verify
const en = flatten(JSON.parse(fs.readFileSync(path.join(localesDir, 'en.json'), 'utf8')))
const enKeys = Object.keys(en)
let ok = true
for (const lang of TARGET_LANGS) {
const loc = flatten(JSON.parse(fs.readFileSync(path.join(localesDir, `${lang}.json`), 'utf8')))
const missing = enKeys.filter((k) => !(k in loc))
if (missing.length) {
console.error(`${lang}: still ${missing.length} missing keys`)
ok = false
}
}
console.log(ok ? '\nAll locales complete.' : '\nSome keys still missing.')

View File

@@ -0,0 +1,145 @@
#!/usr/bin/env python3
"""Generate flat i18n-overrides/*.json for keys still equal to en while fr differs."""
from __future__ import annotations
import json
import re
import sys
import time
from pathlib import Path
from deep_translator import GoogleTranslator
ROOT = Path(__file__).resolve().parents[1]
LOCALES = ROOT / "locales"
OUT_DIR = Path(__file__).resolve().parent / "i18n-overrides"
LANG_TARGETS = {
"ja": "ja",
"ko": "ko",
"zh": "zh-CN",
"hi": "hi",
"fa": "fa",
}
MISSING_11 = [
"ai.featureLocked",
"ai.quotaExceeded",
"profile.tab",
"about.tab",
"appearance.tab",
"usageMeter.featureReformulate",
"usageMeter.featureChat",
"usageMeter.featureBrainstormCreate",
"usageMeter.featureBrainstormExpand",
"usageMeter.featureBrainstormEnrich",
"billing.tab",
]
PERSIAN_DIGITS = "۰۱۲۳۴۵۶۷۸۹"
def flatten_leaves(obj: dict, prefix: str = "") -> dict[str, str]:
out: dict[str, str] = {}
for k, v in obj.items():
path = f"{prefix}.{k}" if prefix else k
if isinstance(v, dict):
out.update(flatten_leaves(v, path))
elif isinstance(v, str):
out[path] = v
return out
def to_persian_digits(text: str) -> str:
return re.sub(r"\d", lambda m: PERSIAN_DIGITS[int(m.group())], text)
def collect_override_keys(en: dict[str, str], fr: dict[str, str], loc: dict[str, str], lang: str) -> list[str]:
fr_translated = [k for k in en if k in fr and fr[k] != en[k]]
keys = {k for k in fr_translated if loc.get(k, en.get(k)) == en[k]}
if lang != "fa":
keys.update(MISSING_11)
return sorted(keys)
def translate_unique(texts: list[str], target_code: str, batch_size: int = 30) -> dict[str, str]:
translator = GoogleTranslator(source="en", target=target_code)
mapping: dict[str, str] = {}
for i in range(0, len(texts), batch_size):
batch = texts[i : i + batch_size]
try:
outs = translator.translate_batch(batch)
except Exception as e:
print(f" batch error ({e}), per-item…", flush=True)
outs = []
for t in batch:
try:
outs.append(translator.translate(t))
except Exception:
outs.append(t)
time.sleep(0.2)
if not isinstance(outs, list) or len(outs) != len(batch):
outs = batch
for src, dst in zip(batch, outs):
mapping[src] = dst if isinstance(dst, str) and dst.strip() else src
time.sleep(0.5)
print(f"{min(i + batch_size, len(texts))}/{len(texts)}", flush=True)
return mapping
def post_process(lang: str, key: str, en_val: str, translated: str) -> str:
if lang == "fa" and re.search(r"\d", translated):
translated = to_persian_digits(translated)
# Momento note-taking: keep common product tokens
if key.endswith(".technology.ai") or key == "about.technology.ai":
if lang == "ja":
return "AI"
if lang == "zh":
return "AI"
if lang == "ko":
return "AI"
if lang == "hi":
return "AI"
if lang == "fa":
return "هوش مصنوعی"
if key == "about.technology.ui":
ui_map = {"ja": "UI", "ko": "UI", "zh": "界面", "hi": "UI", "fa": "رابط کاربری"}
return ui_map.get(lang, translated)
return translated
def main() -> int:
en = flatten_leaves(json.loads((LOCALES / "en.json").read_text(encoding="utf-8")))
fr = flatten_leaves(json.loads((LOCALES / "fr.json").read_text(encoding="utf-8")))
OUT_DIR.mkdir(parents=True, exist_ok=True)
for lang, google_target in LANG_TARGETS.items():
loc = flatten_leaves(json.loads((LOCALES / f"{lang}.json").read_text(encoding="utf-8")))
keys = collect_override_keys(en, fr, loc, lang)
print(f"\n=== {lang}.json — {len(keys)} override keys", flush=True)
text_to_keys: dict[str, list[str]] = {}
for k in keys:
text_to_keys.setdefault(en[k], []).append(k)
unique = list(text_to_keys.keys())
trans_map = translate_unique(unique, google_target)
overrides: dict[str, str] = {}
for src, key_list in text_to_keys.items():
tr = trans_map.get(src, src)
for k in key_list:
overrides[k] = post_process(lang, k, en[k], tr)
out_path = OUT_DIR / f"{lang}.json"
out_path.write_text(
json.dumps(overrides, ensure_ascii=False, indent=2) + "\n",
encoding="utf-8",
)
print(f" Wrote {out_path} ({len(overrides)} keys)", flush=True)
return 0
if __name__ == "__main__":
raise SystemExit(main())

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,184 @@
{
"sidebar.sharedNotebookBadge": "· المشاركة",
"notes.ideaOrigin": "أصل الفكرة",
"notes.noNoteLink": "فكرة توليدية بحتة",
"notes.dismiss": "غير ذات صلة",
"ai.contextSourceHeading": "مصدر السياق",
"ai.tones.professional": "احترافي",
"ai.tones.creative": "مبدع",
"ai.tones.academic": "أكاديمي",
"ai.tones.casual": "استرخاء",
"settings.themeBaseGroup": "عرض",
"settings.themePalettesGroup": "لوحات الألوان",
"settings.themeSepia": "بني داكن",
"settings.themeMidnight": "منتصف الليل",
"settings.themeGreen": "أخضر",
"settings.themeLavender": "لافندر",
"settings.themeSand": "رمل",
"settings.themeOcean": "محيط",
"settings.themeSunset": "غروب",
"settings.themeBlue": "أزرق",
"aiSettings.title": "منظمة العفو الدولية",
"admin.ai.providerOllamaOption": "🦙 أولاما (محلي ومجاني)",
"admin.ai.providerCustomOption": "🔧 متوافق مع OpenAI المخصص",
"admin.users.tierUpdateSuccess": "تم تحديث الاشتراك إلى {tier}",
"admin.users.tierUpdateFailed": "فشل تحديث الاشتراك",
"admin.users.table.subscription": "الاشتراك",
"admin.tools.brave": "واجهة برمجة تطبيقات البحث الشجاع",
"dataManagement.title": "بيانات",
"appearance.fontInterDefault": "إنتر (افتراضي)",
"usageMeter.packName": "حزمة اكتشاف الذكاء الاصطناعي",
"usageMeter.featureSearch": "بحث",
"usageMeter.featureTags": "التسميات",
"usageMeter.featureTitles": "الأوراق المالية",
"usageMeter.unlimited": "غير محدود",
"usageMeter.remaining": "{عدد} متبقي",
"usageMeter.upgradeTitle": "اذهب برو",
"usageMeter.upgradeDescription": "لقد استخدمت جميع الاعتمادات من حزمة اكتشاف الذكاء الاصطناعي. قم بالترقية إلى Pro للحصول على أحرف كبيرة وميزات إضافية.",
"usageMeter.proIncludes": "برو يشمل:",
"usageMeter.proSearch": "100 عملية بحث دلالية / شهر",
"usageMeter.proTags": "200 ملصق تلقائي / شهر",
"usageMeter.proTitles": "200 عنوان سيارة / شهر",
"usageMeter.proReformulate": "50 إعادة صياغة / شهر",
"usageMeter.proChat": "100 رسالة دردشة / شهر",
"usageMeter.later": "لاحقاً",
"usageMeter.upgradePricing": "اذهب برو",
"usageMeter.addApiKey": "استخدم مفتاح API الخاص بك (BYOK)",
"generalSettings.title": "الجنرالات",
"agents.form.back": "خلف",
"agents.help.howToUseContent": "1. انقر على **\"الوكيل الجديد\"** (أو ابدأ بـ **القالب** في أسفل الصفحة)\n2. اختر **نوع الوكيل** (باحث، مراقب، مشرف، مخصص)\n3. أعطه **اسمًا** واملأ الحقول الخاصة بالنوع\n4. اختر بشكل اختياري **دفتر ملاحظات مستهدفًا** أو احفظ النتائج\n5. حدد **التردد** (يدويًا = تقوم بتشغيله بنفسك)\n6. انقر فوق **إنشاء**، ثم اضغط على الزر **تنفيذ** الموجود على بطاقة الوكيل\n7. بمجرد الانتهاء، تظهر ملاحظة جديدة في دفتر ملاحظاتك المستهدف",
"agents.help.advancedContent": "انقر على **\"الوضع المتقدم\"** في أسفل النموذج للوصول إلى الإعدادات الإضافية.\n\n### تعليمات الذكاء الاصطناعي\n\nيتيح لك هذا الحقل **تجاوز موجه النظام الافتراضي** للوكيل. إذا تركته فارغًا، فسيستخدم الوكيل مطالبة تلقائية تتناسب مع نوعه.\n\n**لماذا تستخدمه؟** أنت تريد التحكم في سلوك الوكيل تمامًا. على سبيل المثال:\n- \"اكتب الملخص باللغة الإنجليزية، حتى لو كانت المصادر باللغة الفرنسية\"\n- \"قم بتنظيم الملاحظة باستخدام الأقسام: السياق، النقاط الرئيسية، الرأي الشخصي\"\n- \"تجاهل المقالات التي مضى عليها أكثر من 30 يومًا وركز على الأخبار الأخيرة\"\n- \"لكل موضوع تم اكتشافه، يقدم 3 طرق للدراسة المتعمقة مع الروابط\"\n\n> **ملاحظة:** تحل تعليماتك محل التعليمات الافتراضية، وليس إضافة إليها.\n\n### الحد الأقصى للتكرارات\n\nهذا هو **الحد الأقصى لعدد الدورات** التي يمكن للوكيل تنفيذها. دورة واحدة = يفكر الوكيل، ويستدعي أداة، ويقرأ النتيجة، ثم يقرر الإجراء التالي.\n\n- **3-5 تكرارات:** للمهام البسيطة (نسخ صفحة واحدة)\n- **10 تكرارات (افتراضي):** توازن جيد في معظم الحالات\n- **15-25 تكرارًا:** لعمليات البحث العميق حيث يجب على الوكيل استكشاف عدة طرق\n\n> **تنبيه:** المزيد من التكرارات = المزيد من الوقت وربما المزيد من تكاليف واجهة برمجة التطبيقات (API).",
"agents.help.frequencyContent": "| التردد | السلوك\n|---------------|------------\n| **دليل** | قمت بالنقر فوق \"تشغيل\" - لا توجد جدولة تلقائية\n| **كل ساعة** | يعمل كل ساعة\n| **يوميا** | يعمل مرة واحدة في اليوم\n| **أسبوعي** | يعمل مرة واحدة في الأسبوع\n| **شهري** | يتم تشغيله مرة واحدة في الشهر\n\n> **نصيحة:** ابدأ بـ \"يدويًا\" لاختبار وكيلك، ثم قم بالتبديل إلى التردد التلقائي بمجرد الرضا.",
"agents.help.targetNotebookContent": "عندما يكمل الوكيل مهمته، **ينشئ ملاحظة**. يحدد **دفتر الملاحظات المستهدف** الوجهة التي ستذهب إليها:\n\n- **البريد الوارد** (افتراضي) — تنتقل الملاحظة إلى ملاحظاتك العامة\n- **دفتر ملاحظات محدد** — اختر دفتر ملاحظات للحفاظ على تنظيم النتائج\n\n> **نصيحة:** قم بإنشاء دفتر ملاحظات مخصص مثل \"تقارير الوكيل\" لتجميع المحتوى الآلي بالكامل بشكل مركزي.",
"richTextEditor.imageUrlPlaceholder": "https://example.com/image.png",
"brainstorm.title": "موجات الفكر",
"brainstorm.subtitle": "توسيع أبعاد الإمكانات",
"brainstorm.placeholder": "أدخل مفهومًا لاستكشافه...",
"brainstorm.generating": "الذكاء الاصطناعي يحصد بذور الفكر...",
"brainstorm.newBrainstorm": "العصف الذهني الجديد",
"brainstorm.noSessions": "لا العصف الذهني حتى الآن",
"brainstorm.startOne": "للبدء",
"brainstorm.sessions": "جلسات العصف الذهني",
"brainstorm.seedLabel": "فكرة المصدر",
"brainstorm.brainstormThisIdea": "طرح هذه الفكرة",
"brainstorm.startBrainstorm": "ابدأ العصف الذهني",
"brainstorm.spatialMode": "وضع استكشاف الفضاء",
"brainstorm.wave1": "الموجة 1",
"brainstorm.wave2": "الموجة 2",
"brainstorm.wave3": "الموجة 3",
"brainstorm.export": "يصدّر",
"brainstorm.exporting": "يصدّر...",
"brainstorm.wave": "موجة",
"brainstorm.novelty": "أصالة",
"brainstorm.originConnection": "الارتباط بالأصل",
"brainstorm.linkedNotes": "ملاحظات ذات صلة",
"brainstorm.deepen": "حفر",
"brainstorm.deepening": "جيل...",
"brainstorm.extract": "قم بإنشاء ملاحظة",
"brainstorm.converting": "تحويل...",
"brainstorm.dismiss": "غير ذات صلة",
"brainstorm.noteCreated": "تم إنشاء الملاحظة",
"brainstorm.ideas": "أفكار",
"brainstorm.cancel": "يلغي",
"brainstorm.delete": "يمسح",
"brainstorm.ideaOrigin": "أصل الفكرة",
"brainstorm.noNoteLink": "فكرة توليدية بحتة",
"brainstorm.derived_from": "مشتقة من",
"brainstorm.opposes": "في معارضة",
"brainstorm.extends": "يمتد",
"brainstorm.synthesizes": "توليف",
"brainstorm.transposes": "تبديل",
"brainstorm.none_found": "لا يوجد رابط",
"brainstorm.viewNote": "انظر الملاحظة",
"brainstorm.addIdea": "أضف فكرة",
"brainstorm.manualIdeaPrompt": "عنوان فكرتك:",
"brainstorm.invite": "يدعو",
"brainstorm.linkCopied": "تم نسخ رابط الدعوة!",
"brainstorm.shareDialogTitle": "شارك العصف الذهني",
"brainstorm.shareSearchLabel": "ابحث عن شخص",
"brainstorm.shareNameOrEmailPlaceholder": "الاسم أو البريد الإلكتروني…",
"brainstorm.shareSubmit": "يشارك",
"brainstorm.shareSubmitting": "إرسال…",
"brainstorm.shareFooterHint": "سيتلقى الشخص إشعارًا بالقبول أو الرفض.",
"brainstorm.sharePublicLink": "الرابط العام",
"brainstorm.shareGuestsCanEdit": "السماح للضيوف بالتحرير",
"brainstorm.feedbackInviteSent": "تم إرسال الدعوة!",
"brainstorm.feedbackInviteResent": "عادت الدعوة!",
"brainstorm.feedbackAlreadyShared": "هذا الشخص لديه حق الوصول إلى هذا العصف الذهني بالفعل.",
"brainstorm.feedbackAlreadyPending": "هناك دعوة معلقة بالفعل لهذا الشخص.",
"brainstorm.feedbackGenericError": "خطأ",
"brainstorm.unnamedPerson": "لم يذكر اسمه",
"brainstorm.canvasEditTitleReply": "إجابة",
"brainstorm.canvasEditTitleNewIdea": "فكرة جديدة",
"brainstorm.canvasPlaceholderReply": "إجابتك…",
"brainstorm.canvasPlaceholderIdea": "فكرتك…",
"brainstorm.canvasShortcutSave": "يحفظ",
"brainstorm.canvasShortcutCancel": "يلغي",
"brainstorm.canvasChildBranch": "طفل",
"brainstorm.canvasDoubleClickHint": "انقر نقرًا مزدوجًا لإضافة فكرة",
"brainstorm.ideaDetailConnection": "اتصال",
"brainstorm.ideaDetailNovelty": "أصالة",
"brainstorm.ideaDetailWave": "موجة",
"brainstorm.waveFlavorAnalogy": "تشبيه",
"brainstorm.liveCollaborationTitle": "التعاون المباشر",
"brainstorm.liveStatus": "يعيش",
"brainstorm.liveYouMarker": "(أنت)",
"brainstorm.liveOtherParticipants": "{عدد} مشاركين آخرين",
"brainstorm.guestReadOnlyNotice": "أنت تشاهد هذا العصف الذهني كضيف. قم بتسجيل الدخول للتحرير.",
"brainstorm.impactNotesEnriched": "{count} ملاحظة (ملاحظات) غنية",
"brainstorm.impactNotesMarkedDry": "{count} ملاحظة (ملاحظات) تم وضع علامة عليها جافة",
"brainstorm.exportNotebookPrefix": "دفتر :",
"brainstorm.playbackStep": "الخطوة {الحالية}/{الإجمالي}",
"brainstorm.playbackStepsCount": "{عدد} خطوات",
"brainstorm.playbackReturnToLive": "العودة للعيش",
"brainstorm.canvasWaitingHint": "اللوحة تنتظر شرارتك...",
"brainstorm.seedNodeBadge": "بذور",
"brainstorm.originalSeedDescription": "فكرة المصدر الأولي",
"brainstorm.convertedToNoteStatus": "تم تحويله إلى تصنيف",
"brainstorm.toastExpandSuccess": "أفكار موسعة!",
"brainstorm.toastExpandFailed": "فشل التوسيع",
"brainstorm.toastDismissSuccess": "تم رفض الفكرة",
"brainstorm.toastDismissFailed": "فشل الفجوة",
"brainstorm.toastConvertSuccess": "تحولت الفكرة إلى مذكرة!",
"brainstorm.toastConvertFailed": "فشل التحويل",
"brainstorm.toastExportNoteSuccess": "تصديرها كملاحظة!",
"brainstorm.toastExportFailed": "فشل التصدير",
"brainstorm.legendSeed": "بذرة",
"brainstorm.legendDisruptions": "الانفصال",
"brainstorm.exportFailedMessage": "فشل التصدير",
"brainstorm.exportDefaultNoteTitle": "توليف",
"brainstorm.exportOpening": "افتتاح…",
"brainstorm.ownerBadge": "مالك",
"brainstorm.waveBadge": "موجة {موجة}",
"byokSettings.title": "مفاتيح API الخاصة بك (BYOK)",
"byokSettings.description": "قم بتوصيل مفاتيح البائع الخاصة بك لتجاوز حصص Discovery Pack. يتم تشفير المفاتيح في حالة الراحة.",
"byokSettings.badgeActive": "BYOK نشط",
"byokSettings.tierRequired": "يتطلب BYOK اشتراك Pro أو أعلى.",
"byokSettings.provider": "مزود",
"byokSettings.providerPlaceholder": "اختر موردًا",
"byokSettings.alias": "الصياغة (اختياري)",
"byokSettings.aliasPlaceholder": "السابق. OpenAI برو",
"byokSettings.apiKey": "مفتاح واجهة برمجة التطبيقات",
"byokSettings.save": "حفظ المفتاح",
"byokSettings.saved": "مفتاح API المسجل",
"byokSettings.deleted": "تمت إزالة مفتاح API",
"byokSettings.error": "غير قادر على تسجيل المفتاح",
"byokSettings.loadError": "غير قادر على تحميل المفاتيح",
"byokSettings.loading": "تحميل...",
"byokSettings.empty": "لم يتم تكوين مفتاح API.",
"byokSettings.confirmDelete": "هل تريد حذف مفتاح واجهة برمجة التطبيقات هذا نهائيًا؟",
"billing.enterpriseTitle": "عمل",
"landing.pricing.perUser": "+ 3.90 يورو لكل مستخدم",
"landing.pricing.perUserAnnual": "+ 2.90 يورو لكل مستخدم، يتم إصدار الفاتورة سنويًا",
"ai.featureLocked": "تتطلب هذه الميزة خطة PRO أو أعلى.",
"ai.quotaExceeded": "تم الوصول إلى الحد الشهري. إعادة تعيين الشهر المقبل.",
"profile.tab": "حساب تعريفي",
"about.tab": "عن",
"appearance.tab": "مظهر",
"billing.tab": "الفواتير",
"usageMeter.featureChat": "رسائل الذكاء الاصطناعي",
"usageMeter.featureReformulate": "إعادة الصياغة",
"usageMeter.featureBrainstormCreate": "إبداعات العصف الذهني",
"usageMeter.featureBrainstormExpand": "ملحقات العصف الذهني",
"usageMeter.featureBrainstormEnrich": "إثراء العصف الذهني"
}

View File

@@ -0,0 +1,312 @@
{
"about.support.feedback": "Feedback",
"about.support.title": "Support",
"about.tab": "Über",
"about.technology.backend": "Backend",
"about.technology.frontend": "Frontend",
"about.technology.ui": "Benutzeroberfläche",
"admin.ai.providerCustomOption": "🔧 Benutzerdefiniert (OpenAI-kompatibel)",
"admin.ai.providerOllamaOption": "🦙 Ollama (lokal & kostenlos)",
"admin.chat": "KI-Chat",
"admin.dashboard.title": "Dashboard",
"admin.email.activeAuto": "Automodus: Resend wird zuerst verwendet, SMTP als Fallback.",
"admin.email.activeProvider": "Aktiver Anbieter",
"admin.email.activeSmtp": "Automodus: SMTP wird verwendet (Resend nicht konfiguriert).",
"admin.email.keySet": "Schlüssel konfiguriert",
"admin.email.noneConfigured": "Kein E-Mail-Dienst konfiguriert. Richten Sie Resend oder SMTP ein.",
"admin.email.status": "Dienststatus",
"admin.email.testFail": "Test fehlgeschlagen",
"admin.email.testOk": "Test bestanden",
"admin.lab": "Das Lab",
"admin.sidebar.dashboard": "Dashboard",
"admin.smtp.host": "Host",
"admin.tools.brave": "Brave Search API",
"admin.users.name": "Name",
"admin.users.table.name": "Name",
"admin.users.table.subscription": "Abonnement",
"admin.users.tierUpdateFailed": "Abonnement konnte nicht aktualisiert werden",
"admin.users.tierUpdateSuccess": "Abonnement auf {tier} aktualisiert",
"admin.workspace": "Arbeitsbereich",
"agents.filterAll": "Alle",
"agents.form.back": "Zurück",
"agents.form.includeImages": "Bilder einbeziehen",
"agents.form.includeImagesHint": "Bilder von gescrapten Seiten extrahieren und der generierten Notiz anhängen",
"agents.form.name": "Name",
"agents.form.slideThemes.bohemian": "Bohemian",
"agents.form.urlsOptional": "(optional)",
"agents.help.advancedContent": "Klicken Sie unten im Formular auf **„Erweiterter Modus“**, um zusätzliche Einstellungen zu öffnen.\n\n### KI-Anweisungen\n\nIn diesem Feld können Sie den **Standard-Systemprompt des Agenten ersetzen**. Bleibt es leer, nutzt der Agent einen automatischen, an seinen Typ angepassten Prompt.\n\n**Warum nutzen?** Sie möchten das Verhalten des Agenten genau steuern. Zum Beispiel:\n- „Fasse die Zusammenfassung auf Englisch, auch wenn die Quellen auf Französisch sind“\n- „Strukturiere die Notiz mit Abschnitten: Kontext, Kernpunkte, persönliche Meinung“\n- „Ignoriere Artikel älter als 30 Tage und konzentriere dich auf aktuelle Nachrichten“\n- „Schlage zu jedem erkannten Thema 3 Vertiefungspfade mit Links vor“\n\n> **Hinweis:** Ihre Anweisungen ersetzen die Standardwerte, sie ergänzen sie nicht.\n\n### Max. Iterationen\n\nDas ist die **maximale Anzahl von Zyklen**, die der Agent ausführen kann. Ein Zyklus = der Agent denkt nach, ruft ein Tool auf, liest das Ergebnis und entscheidet die nächste Aktion.\n\n- **35 Iterationen:** für einfache Aufgaben (Scraping einer einzelnen Seite)\n- **10 Iterationen (Standard):** guter Kompromiss für die meisten Fälle\n- **1525 Iterationen:** für tiefe Recherchen mit mehreren Spuren\n\n> **Achtung:** Mehr Iterationen = mehr Zeit und potenziell höhere API-Kosten.",
"agents.help.frequencyContent": "| Häufigkeit | Verhalten\n|-----------|----------\n| **Manuell** | Sie klicken selbst auf „Ausführen“ — keine automatische Planung\n| **Stündlich** | Läuft jede Stunde\n| **Täglich** | Läuft einmal pro Tag\n| **Wöchentlich** | Läuft einmal pro Woche\n| **Monatlich** | Läuft einmal pro Monat\n\n> **Tipp:** Starten Sie mit „Manuell“, um Ihren Agenten zu testen, und wechseln Sie dann zu einer automatischen Häufigkeit, wenn Sie mit den Ergebnissen zufrieden sind.",
"agents.help.howToUseContent": "1. Klicken Sie auf **„Neuer Agent“** (oder starten Sie mit einer **Vorlage** unten auf der Seite)\n2. Wählen Sie einen **Agententyp** (Researcher, Monitor, Observer, Benutzerdefiniert)\n3. Vergeben Sie einen **Namen** und füllen Sie die typspezifischen Felder aus\n4. Wählen Sie optional ein **Ziel-Notizbuch**, in dem Ergebnisse gespeichert werden\n5. Wählen Sie eine **Häufigkeit** (Manuell = Sie starten ihn selbst)\n6. Klicken Sie auf **Erstellen**, dann auf **Ausführen** auf der Agentenkarte\n7. Nach Abschluss erscheint eine neue Notiz in Ihrem Ziel-Notizbuch",
"agents.help.targetNotebookContent": "Wenn ein Agent seine Aufgabe beendet, **erstellt er eine Notiz**. Das **Ziel-Notizbuch** bestimmt, wohin sie geht:\n\n- **Posteingang** (Standard) — die Notiz landet bei Ihren allgemeinen Notizen\n- **Bestimmtes Notizbuch** — wählen Sie ein Notizbuch, um Agentenergebnisse zu ordnen\n\n> **Tipp:** Legen Sie ein eigenes Notizbuch wie „Agentenberichte“ an, um automatisch erzeugte Inhalte an einem Ort zu sammeln.",
"agents.newBadge": "Neu",
"agents.noResults": "Kein Agent entspricht Ihrer Suche.",
"agents.schedule.dayOfMonth": "Tag im Monat",
"agents.schedule.dayOfWeek": "Wochentag",
"agents.schedule.days.fri": "Freitag",
"agents.schedule.days.mon": "Montag",
"agents.schedule.days.sat": "Samstag",
"agents.schedule.days.sun": "Sonntag",
"agents.schedule.days.thu": "Donnerstag",
"agents.schedule.days.tue": "Dienstag",
"agents.schedule.days.wed": "Mittwoch",
"agents.schedule.nextRun": "Nächste Ausführung",
"agents.schedule.pending": "Auslösung ausstehend",
"agents.schedule.time": "Uhrzeit",
"agents.searchPlaceholder": "Agenten suchen…",
"agents.toasts.autoRunError": "Agent „{name}“ ist bei der automatischen Ausführung fehlgeschlagen",
"agents.toasts.autoRunSuccess": "Agent „{name}“ wurde automatisch erfolgreich ausgeführt",
"agents.types.scraper": "Beobachter",
"ai.action.describeImages": "Bilder beschreiben",
"ai.chatTab": "Chat",
"ai.contextSourceHeading": "Kontextquelle",
"ai.featureLocked": "Diese Funktion erfordert den PRO-Plan oder höher.",
"ai.generate.styleMinimal": "Minimal",
"ai.generate.styleProfessional": "Professionell",
"ai.generateTitleFromImage": "Titel aus Bild generieren",
"ai.noImagesError": "Keine Bilder in dieser Notiz",
"ai.overview": "Überblick",
"ai.quotaExceeded": "Monatliches Limit erreicht. Wird nächsten Monat zurückgesetzt.",
"ai.resource.urlLabel": "URL (optional)",
"ai.titleGenerated": "Titel aus Bild generiert",
"ai.tones.academic": "Akademisch",
"ai.tones.casual": "Locker",
"ai.tones.creative": "Kreativ",
"ai.tones.professional": "Professionell",
"aiSettings.providerOpenAI": "OpenAI (Cloud)",
"aiSettings.title": "KI",
"appearance.fontInterDefault": "Inter (Standard)",
"appearance.selectTheme": "Design wählen",
"appearance.tab": "Erscheinungsbild",
"auth.name": "Name",
"auth.signOut": "Abmelden",
"billing.enterpriseTitle": "Enterprise",
"billing.tab": "Abrechnung",
"brainstorm.addIdea": "Idee hinzufügen",
"brainstorm.brainstormThisIdea": "Diese Idee brainstormen",
"brainstorm.cancel": "Abbrechen",
"brainstorm.canvasChildBranch": "Kind",
"brainstorm.canvasDoubleClickHint": "Doppelklicken, um eine Idee hinzuzufügen",
"brainstorm.canvasEditTitleNewIdea": "Neue Idee",
"brainstorm.canvasEditTitleReply": "Antwort",
"brainstorm.canvasPlaceholderIdea": "Ihre Idee…",
"brainstorm.canvasPlaceholderReply": "Ihre Antwort…",
"brainstorm.canvasShortcutCancel": "abbrechen",
"brainstorm.canvasShortcutSave": "speichern",
"brainstorm.canvasWaitingHint": "Die Leinwand wartet auf Ihren Funken…",
"brainstorm.convertedToNoteStatus": "In Notiz umgewandelt",
"brainstorm.converting": "Wird umgewandelt…",
"brainstorm.deepen": "Vertiefen",
"brainstorm.deepening": "Wird generiert…",
"brainstorm.delete": "Löschen",
"brainstorm.derived_from": "Abgeleitet von",
"brainstorm.dismiss": "Nicht relevant",
"brainstorm.export": "Exportieren",
"brainstorm.exportDefaultNoteTitle": "Synthese",
"brainstorm.exportFailedMessage": "Export fehlgeschlagen",
"brainstorm.exportNotebookPrefix": "Notizbuch:",
"brainstorm.exportOpening": "Wird geöffnet…",
"brainstorm.exporting": "Export läuft…",
"brainstorm.extends": "Erweitert",
"brainstorm.extract": "Notiz erstellen",
"brainstorm.feedbackAlreadyPending": "Für diese Person liegt bereits eine ausstehende Einladung vor.",
"brainstorm.feedbackAlreadyShared": "Diese Person hat bereits Zugriff auf diesen Brainstorm.",
"brainstorm.feedbackGenericError": "Fehler",
"brainstorm.feedbackInviteResent": "Einladung erneut gesendet!",
"brainstorm.feedbackInviteSent": "Einladung gesendet!",
"brainstorm.generating": "Die KI sammelt Gedankensamen…",
"brainstorm.guestReadOnlyNotice": "Sie sehen diesen Brainstorm als Gast. Melden Sie sich an, um zu bearbeiten.",
"brainstorm.ideaDetailConnection": "Verbindung",
"brainstorm.ideaDetailNovelty": "Neuheit",
"brainstorm.ideaDetailWave": "Welle",
"brainstorm.ideaOrigin": "Ursprung der Idee",
"brainstorm.ideas": "Ideen",
"brainstorm.impactNotesEnriched": "{count} Notiz(en) angereichert",
"brainstorm.impactNotesMarkedDry": "{count} Notiz(en) als „trocken“ markiert",
"brainstorm.invite": "Einladen",
"brainstorm.legendDisruptions": "Brüche",
"brainstorm.legendSeed": "Samen",
"brainstorm.linkCopied": "Einladungslink kopiert!",
"brainstorm.linkedNotes": "Verknüpfte Notizen",
"brainstorm.liveCollaborationTitle": "Live-Zusammenarbeit",
"brainstorm.liveOtherParticipants": "{count} weitere Teilnehmer",
"brainstorm.liveStatus": "Live",
"brainstorm.liveYouMarker": "(Sie)",
"brainstorm.manualIdeaPrompt": "Titel Ihrer Idee:",
"brainstorm.newBrainstorm": "Neuer Brainstorm",
"brainstorm.noNoteLink": "Rein generierte Idee",
"brainstorm.noSessions": "Noch keine Brainstorms",
"brainstorm.none_found": "Keine Notizverknüpfung",
"brainstorm.noteCreated": "Notiz erstellt",
"brainstorm.novelty": "Neuheit",
"brainstorm.opposes": "Im Gegensatz zu",
"brainstorm.originConnection": "Bezug zum Ursprung",
"brainstorm.originalSeedDescription": "Ursprüngliche Ausgangs-Idee",
"brainstorm.ownerBadge": "Inhaber",
"brainstorm.placeholder": "Geben Sie ein Konzept ein, das Sie entfalten möchten…",
"brainstorm.playbackReturnToLive": "Zurück zu Live",
"brainstorm.playbackStep": "Schritt {current}/{total}",
"brainstorm.playbackStepsCount": "{count} Schritte",
"brainstorm.seedLabel": "Ausgangs-Idee",
"brainstorm.seedNodeBadge": "SAMEN",
"brainstorm.sessions": "Brainstorm-Sitzungen",
"brainstorm.shareDialogTitle": "Brainstorm teilen",
"brainstorm.shareFooterHint": "Die Person erhält eine Benachrichtigung zum Annehmen oder Ablehnen.",
"brainstorm.shareGuestsCanEdit": "Gästen Bearbeitung erlauben",
"brainstorm.shareNameOrEmailPlaceholder": "Name oder E-Mail…",
"brainstorm.sharePublicLink": "Öffentlicher Link",
"brainstorm.shareSearchLabel": "Person finden",
"brainstorm.shareSubmit": "Teilen",
"brainstorm.shareSubmitting": "Wird gesendet…",
"brainstorm.spatialMode": "Räumlicher Erkundungsmodus",
"brainstorm.startBrainstorm": "Brainstorm starten",
"brainstorm.startOne": "Einen starten",
"brainstorm.subtitle": "Dimensionen des Potenzials entfalten",
"brainstorm.synthesizes": "Synthetisiert",
"brainstorm.title": "Gedankenwellen",
"brainstorm.toastConvertFailed": "Umwandlung fehlgeschlagen",
"brainstorm.toastConvertSuccess": "Idee in Notiz umgewandelt!",
"brainstorm.toastDismissFailed": "Verwerfen fehlgeschlagen",
"brainstorm.toastDismissSuccess": "Idee verworfen",
"brainstorm.toastExpandFailed": "Erweiterung fehlgeschlagen",
"brainstorm.toastExpandSuccess": "Ideen erweitert!",
"brainstorm.toastExportFailed": "Export fehlgeschlagen",
"brainstorm.toastExportNoteSuccess": "Als Notiz exportiert!",
"brainstorm.transposes": "Transponiert",
"brainstorm.unnamedPerson": "Ohne Namen",
"brainstorm.viewNote": "Notiz anzeigen",
"brainstorm.wave": "Welle",
"brainstorm.wave1": "Welle 1",
"brainstorm.wave2": "Welle 2",
"brainstorm.wave3": "Welle 3",
"brainstorm.waveBadge": "Welle {wave}",
"brainstorm.waveFlavorAnalogy": "Analogie",
"byokSettings.alias": "Bezeichnung (optional)",
"byokSettings.aliasPlaceholder": "z. B. OpenAI Arbeit",
"byokSettings.apiKey": "API-Schlüssel",
"byokSettings.badgeActive": "BYOK aktiv",
"byokSettings.confirmDelete": "Diesen API-Schlüssel dauerhaft entfernen?",
"byokSettings.deleted": "API-Schlüssel entfernt",
"byokSettings.description": "Verbinden Sie eigene LLM-Anbieter-Schlüssel, um die Limits des Entdecker-Pakets zu umgehen. Schlüssel werden verschlüsselt gespeichert.",
"byokSettings.empty": "Noch keine API-Schlüssel konfiguriert.",
"byokSettings.error": "API-Schlüssel konnte nicht gespeichert werden",
"byokSettings.loadError": "API-Schlüssel konnten nicht geladen werden",
"byokSettings.loading": "Schlüssel werden geladen…",
"byokSettings.provider": "Anbieter",
"byokSettings.providerPlaceholder": "Anbieter wählen",
"byokSettings.save": "Schlüssel speichern",
"byokSettings.saved": "API-Schlüssel gespeichert",
"byokSettings.tierRequired": "BYOK erfordert den Pro-Plan oder höher. Upgraden Sie, um Ihre API-Schlüssel zu verbinden.",
"byokSettings.title": "Ihre API-Schlüssel (BYOK)",
"chat.timeoutWarning": "Die Antwort dauert länger als erwartet…",
"common.optional": "Optional",
"dataManagement.title": "Daten",
"diagnostics.checking": "Wird geprüft…",
"diagnostics.description": "Verbindungsstatus Ihres KI-Anbieters prüfen",
"diagnostics.errorStatus": "Fehler",
"diagnostics.operational": "Betriebsbereit",
"documentInfo.tabInfo": "Info",
"general.clean": "Bereinigen",
"general.indexAll": "Alle indexieren",
"general.testConnection": "Verbindung testen",
"generalSettings.title": "Allgemein",
"labHeader.live": "Live",
"labHeader.rename": "Umbenennen",
"labels.title": "Labels",
"landing.footer.community.title": "Community",
"landing.pricing.perUser": "+ 3,90 €/Nutzer",
"landing.pricing.perUserAnnual": "+ 2,90 €/Nutzer, jährlich abgerechnet",
"nav.proPlan": "Pro-Plan",
"notebook.generatingDescription": "Bitte warten…",
"notes.archiveFailed": "Archivierung fehlgeschlagen",
"notes.archived": "Notiz archiviert",
"notes.confirmDeleteTitle": "Notiz löschen",
"notes.content": "Inhalt",
"notes.conversionFailed": "Umwandlung fehlgeschlagen, bleibt in Markdown",
"notes.convertedToRichText": "In Rich Text umgewandelt",
"notes.createFailed": "Notiz konnte nicht erstellt werden",
"notes.deleteFailed": "Notiz konnte nicht gelöscht werden",
"notes.deleted": "Notiz gelöscht",
"notes.dismiss": "Nicht relevant",
"notes.dismissed": "Notiz aus „Zuletzt“ entfernt",
"notes.generalNotes": "Allgemeine Notizen",
"notes.generateTitleFromImage": "Titel aus Bild generieren",
"notes.historyDisabledTitle": "Versionsverlauf",
"notes.historyEnabledDesc": "Versionen dieser Notiz werden ab jetzt gespeichert.",
"notes.historyEnabledTitle": "Verlauf aktiviert!",
"notes.ideaOrigin": "Ursprung der Idee",
"notes.leftShare": "Freigabe entfernt",
"notes.noNoteLink": "Rein generierte Idee",
"notes.restore": "Wiederherstellen",
"notes.sort": "Sortieren",
"notes.suggestTitle": "KI-Titel",
"notes.titleGenerated": "Titel generiert",
"notes.typeRichText": "Rich Text",
"notes.typeText": "Text",
"notes.updateFailed": "Aktualisierung fehlgeschlagen",
"notification.accept": "Annehmen",
"notification.accepted": "Freigabe angenommen",
"notification.decline": "Ablehnen",
"notification.noNotifications": "Keine neuen Benachrichtigungen",
"notification.systemNotification": "System",
"profile.recentNotesUpdateFailed": "Einstellung für zuletzt geänderte Notizen konnte nicht aktualisiert werden",
"profile.recentNotesUpdateSuccess": "Einstellung für zuletzt geänderte Notizen erfolgreich aktualisiert",
"profile.showRecentNotes": "Bereich „Zuletzt“ anzeigen",
"profile.showRecentNotesDescription": "Kürzliche Notizen (letzte 7 Tage) auf der Hauptseite anzeigen",
"profile.tab": "Profil",
"richTextEditor.imageUrlPlaceholder": "https://beispiel.de/bild.png",
"richTextEditor.slashAlignCenter": "Zentrieren",
"richTextEditor.slashText": "Text",
"settings.cardSizeMode": "Notizgröße",
"settings.cardSizeModeDescription": "Zwischen variablen oder einheitlichen Größen wählen",
"settings.cardSizeUniform": "Einheitliche Größe",
"settings.cardSizeVariable": "Variable Größen (klein/mittel/groß)",
"settings.cleanTags": "Verwaiste Labels bereinigen",
"settings.cleanTagsDescription": "Labels entfernen, die von keiner Notiz mehr verwendet werden",
"settings.maintenanceDescription": "Werkzeuge zur Pflege Ihrer Datenbank",
"settings.selectCardSizeMode": "Anzeigemodus wählen",
"settings.semanticIndexing": "Semantische Indexierung",
"settings.semanticIndexingDescription": "Vektoren für alle Notizen erzeugen, um absichtsbasierte Suche zu ermöglichen",
"settings.themeBaseGroup": "Anzeige",
"settings.themeBlue": "Blau",
"settings.themeGreen": "Grün",
"settings.themeLavender": "Lavendel",
"settings.themeMidnight": "Mitternacht",
"settings.themeOcean": "Ozean",
"settings.themePalettesGroup": "Farbpaletten",
"settings.themeSand": "Sand",
"settings.themeSepia": "Sepia",
"settings.themeSunset": "Sonnenuntergang",
"settings.themeSystem": "System",
"sidebar.archive": "Archiv",
"sidebar.clearFilter": "Filter entfernen",
"sidebar.editLabels": "Labels bearbeiten",
"sidebar.labels": "Labels",
"sidebar.reminders": "Erinnerungen",
"sidebar.sharedNotebookBadge": "· Geteilt",
"sidebar.sortAlpha": "A → Z",
"sidebar.trash": "Papierkorb",
"support.domainSSL": "Domain & SSL:",
"testPages.titleSuggestions.status": "Status:",
"usageMeter.addApiKey": "Eigene API-Schlüssel verwenden (BYOK)",
"usageMeter.featureBrainstormCreate": "Brainstorm-Erstellungen",
"usageMeter.featureBrainstormEnrich": "Brainstorm-Anreicherungen",
"usageMeter.featureBrainstormExpand": "Brainstorm-Erweiterungen",
"usageMeter.featureChat": "KI-Nachrichten",
"usageMeter.featureReformulate": "Umformulierungen",
"usageMeter.featureSearch": "Suche",
"usageMeter.featureTags": "Labels",
"usageMeter.featureTitles": "Titel",
"usageMeter.later": "Später",
"usageMeter.packName": "KI-Entdecker-Paket",
"usageMeter.proChat": "100 Chat-Nachrichten / Monat",
"usageMeter.proIncludes": "Pro enthält:",
"usageMeter.proReformulate": "50 Umformulierungen / Monat",
"usageMeter.proSearch": "100 semantische Suchen / Monat",
"usageMeter.proTags": "200 Auto-Labels / Monat",
"usageMeter.proTitles": "200 Auto-Titel / Monat",
"usageMeter.remaining": "{count} übrig",
"usageMeter.unlimited": "Unbegrenzt",
"usageMeter.upgradeDescription": "Sie haben alle Guthaben des KI-Entdecker-Pakets verbraucht. Upgraden Sie auf Pro für höhere Limits und zusätzliche Funktionen.",
"usageMeter.upgradePricing": "Auf Pro upgraden",
"usageMeter.upgradeTitle": "Auf Pro upgraden"
}

View File

@@ -0,0 +1,347 @@
{
"about.tab": "Acerca de",
"about.technology.backend": "back-end",
"about.technology.frontend": "Interfaz",
"about.technology.ui": "Interfaz",
"admin.ai.providerCustomOption": "🔧 Compatible con OpenAI personalizado",
"admin.ai.providerLMStudioOption": "🖥️ LM Studio (local)",
"admin.ai.providerOllamaOption": "🦙 Ollama (local y gratuito)",
"admin.aiTest.error": "Error :",
"admin.chat": "Gato IA",
"admin.email.activeAuto": "Modo automático: el reenvío se utilizará como prioridad y SMTP como respaldo.",
"admin.email.activeProvider": "Proveedor activo",
"admin.email.activeSmtp": "Modo automático: se utilizará SMTP (reenvío no configurado).",
"admin.email.keySet": "clave configurada",
"admin.email.noneConfigured": "No hay ningún servicio de correo electrónico configurado. Configure Reenvío o SMTP.",
"admin.email.status": "Estado del servicio",
"admin.email.testFail": "prueba fallida",
"admin.email.testOk": "prueba pasada",
"admin.lab": "El laboratorio",
"admin.smtp.host": "Anfitrión",
"admin.tools.brave": "API de búsqueda valiente",
"admin.users.table.subscription": "Suscripción",
"admin.users.tierUpdateFailed": "Error al actualizar la suscripción",
"admin.users.tierUpdateSuccess": "Suscripción actualizada a {tier}",
"admin.workspace": "Espacio de trabajo",
"agents.filterAll": "Todo",
"agents.form.back": "Atrás",
"agents.form.includeImages": "Incluir imágenes",
"agents.form.includeImagesHint": "Extraiga imágenes de páginas raspadas y adjúntelas a la nota generada",
"agents.frequencies.manual": "Manual",
"agents.help.advancedContent": "Haga clic en **\"Modo avanzado\"** en la parte inferior del formulario para acceder a configuraciones adicionales.\n\n### Instrucciones de IA\n\nEste campo le permite **anular el mensaje predeterminado del sistema** del agente. Si lo deja vacío, el agente utiliza un mensaje automático adaptado a su tipo.\n\n**¿Por qué usarlo?** Quieres controlar exactamente el comportamiento del agente. Por ejemplo:\n- “Escribir el resumen en inglés, incluso si las fuentes están en francés”\n- “Estructurar la nota con las secciones: Contexto, Puntos clave, Opinión personal”\n- “Ignora artículos de más de 30 días y céntrate en noticias recientes”\n- \"Para cada tema detectado, ofrece 3 vías de estudio en profundidad con enlaces\"\n\n> **Nota:** Sus instrucciones reemplazan las predeterminadas, no es que las agreguen.\n\n### Iteraciones máximas\n\nEste es el **número máximo de ciclos** que el agente puede realizar. Un ciclo = el agente piensa, llama a una herramienta, lee el resultado y luego decide la siguiente acción.\n\n- **3-5 iteraciones:** para tareas simples (raspado de una sola página)\n- **10 iteraciones (predeterminado):** buen equilibrio en la mayoría de los casos\n- **15-25 iteraciones:** para búsquedas profundas donde el agente debe explorar varias vías\n\n> **Atención:** Más iteraciones = más tiempo y potencialmente más costos de API.",
"agents.help.frequencyContent": "| Frecuencia | Comportamiento\n|---------------|------------\n| **Manual** | Hace clic en \"Ejecutar\": no hay programación automática\n| **Cada hora** | Corre cada hora\n| **Diario** | Se ejecuta una vez al día\n| **Semanal** | Se ejecuta una vez por semana.\n| **Mensual** | Se ejecuta una vez al mes\n\n> **Consejo:** Comience con \"Manual\" para probar su agente, luego cambie a la frecuencia automática una vez que esté satisfecho.",
"agents.help.howToUseContent": "1. Haga clic en **\"Nuevo agente\"** (o comience con una **Plantilla** en la parte inferior de la página)\n2. Elija un **tipo de agente** (Investigador, Vigilante, Supervisor, Personalizado)\n3. Asígnale un **nombre** y completa los campos específicos del tipo.\n4. Opcionalmente, elija un **cuaderno de destino** o guarde los resultados.\n5. Seleccione una **frecuencia** (Manual = la ejecuta usted mismo)\n6. Haga clic en **Crear**, luego presione el botón **Ejecutar** en la tarjeta del agente.\n7. Una vez completado, aparece una nueva nota en su cuaderno de destino.",
"agents.help.targetNotebookContent": "Cuando un agente completa su tarea, **crea una nota**. El **cuaderno de destino** determina hacia dónde se dirige:\n\n- **Bandeja de entrada** (predeterminado): la nota va a sus notas generales\n- **Cuaderno específico**: elige un cuaderno para mantener los resultados organizados\n\n> **Consejo:** Cree un cuaderno dedicado como \"Informes de agentes\" para centralizar todo el contenido automatizado.",
"agents.newBadge": "Nuevo",
"agents.noResults": "Ningún agente coincide con su búsqueda.",
"agents.schedule.dayOfMonth": "dia del mes",
"agents.schedule.dayOfWeek": "Día de la semana",
"agents.schedule.days.fri": "Viernes",
"agents.schedule.days.mon": "Lunes",
"agents.schedule.days.sat": "SÁBADO",
"agents.schedule.days.sun": "Domingo",
"agents.schedule.days.thu": "JUEVES",
"agents.schedule.days.tue": "Martes",
"agents.schedule.days.wed": "Miércoles",
"agents.schedule.nextRun": "Próxima ejecución",
"agents.schedule.pending": "Esperando para disparar",
"agents.schedule.time": "Hora",
"agents.searchPlaceholder": "Encuentre un agente...",
"agents.toasts.autoRunError": "El agente \"{name}\" falló durante la ejecución automática",
"agents.toasts.autoRunSuccess": "El agente \"{name}\" se ejecutó automáticamente con éxito",
"agents.toasts.runError": "Error: {error}",
"agents.types.scraper": "Sereno",
"ai.action.describeImages": "Describe las imágenes",
"ai.chatTab": "Discusión",
"ai.contextSourceHeading": "fuente de contexto",
"ai.errorShort": "Error",
"ai.featureLocked": "Esta función requiere el plan PRO o superior.",
"ai.generateTitleFromImage": "Generar título a partir de imagen",
"ai.insightsTab": "Resúmenes",
"ai.noImagesError": "No hay imágenes en esta nota.",
"ai.overview": "Resumen",
"ai.quotaExceeded": "Límite mensual alcanzado. Se restablece el próximo mes.",
"ai.titleGenerated": "Título generado a partir de la imagen.",
"ai.tones.academic": "Académico",
"ai.tones.casual": "Relajado",
"ai.tones.creative": "Creativo",
"ai.tones.professional": "Profesional",
"aiSettings.providerOllama": "Ollama (local)",
"aiSettings.title": "IA",
"appearance.fontInterDefault": "Inter (predeterminado)",
"appearance.selectTheme": "Seleccionar tema",
"appearance.tab": "Apariencia",
"auth.signOut": "Desconectar",
"billing.enterpriseTitle": "Negocio",
"billing.tab": "Facturación",
"brainstorm.addIdea": "Añade una idea",
"brainstorm.aiIdea": "IA",
"brainstorm.brainstormThisIdea": "Haz una lluvia de ideas sobre esta idea",
"brainstorm.cancel": "Cancelar",
"brainstorm.canvasChildBranch": "niño",
"brainstorm.canvasDoubleClickHint": "Haz doble clic para agregar una idea.",
"brainstorm.canvasEditTitleNewIdea": "nueva idea",
"brainstorm.canvasEditTitleReply": "Respuesta",
"brainstorm.canvasPlaceholderIdea": "Tu idea...",
"brainstorm.canvasPlaceholderReply": "Tu respuesta…",
"brainstorm.canvasShortcutCancel": "Cancelar",
"brainstorm.canvasShortcutSave": "ahorrar",
"brainstorm.canvasWaitingHint": "El lienzo espera tu chispa...",
"brainstorm.convertedToNoteStatus": "Convertido a calificación",
"brainstorm.converting": "Conversión...",
"brainstorm.deepen": "Excavar",
"brainstorm.deepening": "Generación...",
"brainstorm.delete": "BORRAR",
"brainstorm.derived_from": "Derivado de",
"brainstorm.dismiss": "No relevante",
"brainstorm.export": "Exportar",
"brainstorm.exportDefaultNoteTitle": "Síntesis",
"brainstorm.exportFailedMessage": "Exportación fallida",
"brainstorm.exportNotebookPrefix": "Computadora portátil :",
"brainstorm.exportOpening": "Apertura…",
"brainstorm.exporting": "Exportar...",
"brainstorm.extends": "Se extiende",
"brainstorm.extract": "crear una nota",
"brainstorm.feedbackAlreadyPending": "Ya hay una invitación pendiente para esta persona.",
"brainstorm.feedbackAlreadyShared": "Esta persona ya tiene acceso a esta lluvia de ideas.",
"brainstorm.feedbackGenericError": "Error",
"brainstorm.feedbackInviteResent": "¡Invitación devuelta!",
"brainstorm.feedbackInviteSent": "¡Invitación enviada!",
"brainstorm.generating": "La IA cosecha semillas de pensamiento...",
"brainstorm.guestReadOnlyNotice": "Estás viendo esta lluvia de ideas como invitado. Inicie sesión para editar.",
"brainstorm.ideaDetailConnection": "Conexión",
"brainstorm.ideaDetailNovelty": "Originalidad",
"brainstorm.ideaDetailWave": "Ola",
"brainstorm.ideaOrigin": "Origen de la idea",
"brainstorm.ideas": "ideas",
"brainstorm.impactNotesEnriched": "{count} nota(s) enriquecida(s)",
"brainstorm.impactNotesMarkedDry": "{count} nota(s) marcada(s) seca(s)",
"brainstorm.invite": "Invitar",
"brainstorm.legendDisruptions": "Rupturas",
"brainstorm.legendSeed": "Semilla",
"brainstorm.linkCopied": "¡Enlace de invitación copiado!",
"brainstorm.linkedNotes": "Notas relacionadas",
"brainstorm.liveCollaborationTitle": "Colaboración en vivo",
"brainstorm.liveOtherParticipants": "{count} otros participantes",
"brainstorm.liveStatus": "Vivir",
"brainstorm.liveYouMarker": "(TÚ)",
"brainstorm.manualIdeaPrompt": "Título de tu idea:",
"brainstorm.newBrainstorm": "Nueva lluvia de ideas",
"brainstorm.noNoteLink": "Idea puramente generativa",
"brainstorm.noSessions": "Aún no hay lluvias de ideas",
"brainstorm.none_found": "Sin enlace",
"brainstorm.noteCreated": "Nota creada",
"brainstorm.novelty": "Originalidad",
"brainstorm.opposes": "En oposición a",
"brainstorm.originConnection": "Enlace con origen",
"brainstorm.originalSeedDescription": "Idea fuente inicial",
"brainstorm.ownerBadge": "Dueño",
"brainstorm.placeholder": "Introduzca un concepto para explorar...",
"brainstorm.playbackReturnToLive": "volver a vivir",
"brainstorm.playbackStep": "Paso {current}/{total}",
"brainstorm.playbackStepsCount": "{count} pasos",
"brainstorm.seedLabel": "Idea fuente",
"brainstorm.seedNodeBadge": "SEMILLA",
"brainstorm.sessions": "Sesiones de lluvia de ideas",
"brainstorm.shareDialogTitle": "Comparte la lluvia de ideas",
"brainstorm.shareFooterHint": "La persona recibirá una notificación para aceptar o rechazar.",
"brainstorm.shareGuestsCanEdit": "Permitir que los invitados editen",
"brainstorm.shareNameOrEmailPlaceholder": "Nombre o correo electrónico…",
"brainstorm.sharePublicLink": "Enlace público",
"brainstorm.shareSearchLabel": "buscar una persona",
"brainstorm.shareSubmit": "Compartir",
"brainstorm.shareSubmitting": "Envío…",
"brainstorm.spatialMode": "Modo de exploración espacial",
"brainstorm.startBrainstorm": "Iniciar la lluvia de ideas",
"brainstorm.startOne": "para empezar",
"brainstorm.subtitle": "Ampliar las dimensiones del potencial.",
"brainstorm.synthesizes": "sintetizar",
"brainstorm.title": "Ondas de pensamiento",
"brainstorm.toastConvertFailed": "La conversión falló",
"brainstorm.toastConvertSuccess": "¡Idea convertida en nota!",
"brainstorm.toastDismissFailed": "Fallo de brecha",
"brainstorm.toastDismissSuccess": "Idea descartada",
"brainstorm.toastExpandFailed": "Fracaso de la ampliación",
"brainstorm.toastExpandSuccess": "¡Ideas ampliadas!",
"brainstorm.toastExportFailed": "Exportación fallida",
"brainstorm.toastExportNoteSuccess": "¡Exportado como nota!",
"brainstorm.transposes": "Transponer",
"brainstorm.unnamedPerson": "Sin nombre",
"brainstorm.viewNote": "Ver nota",
"brainstorm.wave": "Ola",
"brainstorm.wave1": "Ola 1",
"brainstorm.wave2": "Ola 2",
"brainstorm.wave3": "Ola 3",
"brainstorm.waveBadge": "Ola {wave}",
"brainstorm.waveFlavorAnalogy": "Analogía",
"byokSettings.alias": "Redacción (opcional)",
"byokSettings.aliasPlaceholder": "ex. OpenAI profesional",
"byokSettings.apiKey": "Clave API",
"byokSettings.badgeActive": "BYOK activo",
"byokSettings.confirmDelete": "¿Eliminar definitivamente esta clave API?",
"byokSettings.deleted": "Clave API eliminada",
"byokSettings.description": "Conecte sus propias claves de proveedor para eludir las cuotas del paquete Descubrimiento. Las llaves están cifradas en reposo.",
"byokSettings.empty": "No se ha configurado ninguna clave API.",
"byokSettings.error": "No se puede guardar la clave",
"byokSettings.loadError": "No se pueden cargar las llaves",
"byokSettings.loading": "Carga...",
"byokSettings.provider": "Proveedor",
"byokSettings.providerPlaceholder": "Elegir un proveedor",
"byokSettings.save": "Guardar clave",
"byokSettings.saved": "Clave API registrada",
"byokSettings.tierRequired": "El BYOK requiere una suscripción Pro o superior.",
"byokSettings.title": "Sus claves API (BYOK)",
"chat.timeoutWarning": "La respuesta tarda más de lo esperado...",
"common.error": "Error",
"dataManagement.cleanup.button": "Limpiar",
"dataManagement.cleanup.description": "Eliminar etiquetas y conexiones que hagan referencia a notas eliminadas.",
"dataManagement.cleanup.failed": "Error al limpiar",
"dataManagement.cleanup.title": "Limpiar datos huérfanos",
"dataManagement.delete.button": "Eliminar todas las notas",
"dataManagement.delete.confirm": "¿Está seguro? Esta acción eliminará permanentemente todas sus notas.",
"dataManagement.delete.description": "Borrar definitivamente todas tus notas. Esta acción es irreversible.",
"dataManagement.delete.failed": "Error al eliminar notas",
"dataManagement.delete.success": "Todas las notas han sido eliminadas",
"dataManagement.delete.title": "Eliminar todas las notas",
"dataManagement.export.button": "Exportar notas",
"dataManagement.export.description": "Descarga todas tus notas en formato JSON. Incluye todo el contenido, etiquetas y metadatos.",
"dataManagement.export.failed": "Fallo al exportar notas",
"dataManagement.export.success": "Notas exportadas con éxito",
"dataManagement.export.title": "Exportar todas las notas",
"dataManagement.import.button": "Importar notas",
"dataManagement.import.description": "Descarga un archivo JSON para importar notas. Las notas se añadirán a las existentes, no se sustituirán.",
"dataManagement.import.failed": "Fallo al importar notas",
"dataManagement.import.success": "{count} notas importadas",
"dataManagement.import.title": "Importar notas",
"dataManagement.indexing.button": "Reconstruir el índice",
"dataManagement.indexing.description": "Regenerar embeddings para todas las notas para mejorar la búsqueda semántica.",
"dataManagement.indexing.failed": "Error al indexar",
"dataManagement.indexing.success": "Indexación completada: {count} notas procesadas",
"dataManagement.indexing.title": "Reconstruir el índice de búsqueda",
"dataManagement.title": "Datos",
"dataManagement.toolsDescription": "Herramientas para mantener la salud de tu base de datos",
"diagnostics.checking": "Verificación",
"diagnostics.description": "Comprueba el estado de la conexión de tu proveedor de IA",
"diagnostics.errorStatus": "Error",
"diagnostics.operational": "Operacional",
"general.clean": "Limpiar",
"general.indexAll": "Indexar todo",
"general.testConnection": "Probar conexión",
"generalSettings.title": "Generales.",
"labHeader.rename": "Renombrar",
"labels.createLabel": "Crear etiqueta",
"labels.delete": "BORRAR",
"labels.deleteTooltip": "Eliminar etiqueta",
"labels.editLabels": "Modificar las etiquetas",
"labels.editLabelsDescription": "Crear, modificar colores o eliminar etiquetas.",
"labels.filter": "Filtrar por etiqueta",
"labels.filterByLabel": "Filtrar por etiqueta",
"labels.labelColor": "Color de la etiqueta",
"labels.labelName": "Nombre Etiqueta",
"labels.loading": "Carga...",
"labels.manage": "Gestionar etiquetas",
"labels.manageLabels": "Gestionar etiquetas",
"labels.manageLabelsDescription": "Añadir o eliminar etiquetas para esta nota. Haga clic en una etiqueta para cambiar su color.",
"labels.manageTooltip": "Gestionar etiquetas",
"labels.namePlaceholder": "Introduzca el nombre de la etiqueta",
"labels.newLabelPlaceholder": "Crear nueva etiqueta",
"labels.noLabelsFound": "No se ha encontrado ninguna etiqueta.",
"labels.notebookRequired": "⚠️ Las etiquetas solo están disponibles en los cuadernos. Mueva esta nota a un cuaderno primero.",
"labels.selectedLabels": "Etiquetas seleccionadas",
"labels.showLess": "VER MENOS<x id=\"1\"/><x id=\"2\"/>",
"labels.showMore": "Ver más",
"labels.tagAdded": "Etiqueta \"{tag}\" añadida",
"labels.title": "Etiquetas",
"landing.footer.legal.title": "Legal",
"landing.pricing.perUser": "+ 3,90€/usuario",
"landing.pricing.perUserAnnual": "+ 2,90€/usuario, facturación anual",
"notebook.generatingDescription": "Favor de esperar…",
"notebook.selectColor": " Color",
"notes.archiveFailed": "Falló el archivado.",
"notes.archived": "Se añade una nota al expediente",
"notes.color": " Color",
"notes.confirmDeleteTitle": "Borrar nota",
"notes.content": "Contenido",
"notes.conversionFailed": "Falló la conversión, permanece en Markdown",
"notes.convertedToRichText": "Convertido en texto enriquecido",
"notes.createFailed": "No se puede crear la nota",
"notes.deleteFailed": "Falló la eliminación de la nota",
"notes.deleted": "Nota eliminada",
"notes.dismiss": "No relevante",
"notes.dismissed": "Nota retirada de las recientes",
"notes.generalNotes": "Notas generales",
"notes.generateTitleFromImage": "Generar título a partir de imagen",
"notes.historyDisabledTitle": "Historial de versiones",
"notes.historyEnabledDesc": "A partir de ahora se guardarán las versiones de esta nota.",
"notes.historyEnabledTitle": "¡Histórico activado!",
"notes.ideaOrigin": "Origen de la idea",
"notes.leftShare": "Compartir retirado",
"notes.noNoteLink": "Idea puramente generativa",
"notes.remove": "BORRAR",
"notes.restore": "Restablecer",
"notes.sort": "Ordenar",
"notes.suggestTitle": "Título IA",
"notes.titleGenerated": "Título generado",
"notes.updateFailed": "Actualización fallida",
"notification.accept": "Accept",
"notification.accepted": "Se acepta compartir",
"notification.decline": "Declinar",
"notification.noNotifications": "Ninguna notificación",
"paragraphRefactor.formal": "Formal:",
"profile.recentNotesUpdateFailed": "Falló la actualización de la configuración de notas recientes",
"profile.recentNotesUpdateSuccess": "Configuración de notas recientes actualizada con éxito",
"profile.showRecentNotes": "Mostrar la sección Reciente",
"profile.showRecentNotesDescription": "Mostrar notas recientes (últimos 7 días) en la página principal",
"profile.tab": "Perfil",
"settings.cardSizeMode": "Tamaño de las notas",
"settings.cardSizeModeDescription": "Elegir entre notas de diferentes tamaños o uniformes",
"settings.cardSizeUniform": "Talla uniforme",
"settings.cardSizeVariable": "Tamaños variables (pequeño/mediano/grande)",
"settings.cleanTags": "Limpiar etiquetas huérfanas",
"settings.cleanTagsDescription": "Eliminar las etiquetas que ya no son utilizadas por ninguna nota",
"settings.maintenanceDescription": "Herramientas para mantener la salud de tu base de datos",
"settings.selectCardSizeMode": "Activar la vista de página maestra.",
"settings.semanticIndexing": "Indexación semántica",
"settings.semanticIndexingDescription": "Generar vectores para todas las notas para permitir la búsqueda por intención",
"settings.themeBaseGroup": "Pantalla",
"settings.themeBlue": "Azul",
"settings.themeGreen": "Verde",
"settings.themeLavender": "Lavanda",
"settings.themeMidnight": "Medianoche",
"settings.themeOcean": "Océano",
"settings.themePalettesGroup": "Paletas de colores",
"settings.themeSand": "Arena",
"settings.themeSepia": "Sepia",
"settings.themeSunset": "Puesta de sol",
"sidebar.archive": "Archivos",
"sidebar.clearFilter": "Retirar el filtro",
"sidebar.editLabels": "Modificar las etiquetas",
"sidebar.labels": "Etiquetas",
"sidebar.reminders": "Advertencias",
"sidebar.sharedNotebookBadge": "Distribuido",
"sidebar.sortAlpha": "Orden A → Z",
"sidebar.trash": "Papelera",
"testPages.titleSuggestions.error": "Error :",
"usageMeter.addApiKey": "Utilizar su propia clave API (BYOK)",
"usageMeter.featureBrainstormCreate": "Creaciones de brainstorm",
"usageMeter.featureBrainstormEnrich": "Enriquecimientos de brainstorm",
"usageMeter.featureBrainstormExpand": "Expansiones de brainstorm",
"usageMeter.featureChat": "Mensajes IA",
"usageMeter.featureReformulate": "Reformulaciones",
"usageMeter.featureSearch": "Búsqueda",
"usageMeter.featureTags": "Etiquetas",
"usageMeter.featureTitles": "Títulos",
"usageMeter.later": "Más tarde",
"usageMeter.packName": "Pack descubrimiento IA",
"usageMeter.proChat": "100 mensajes de chat / mes",
"usageMeter.proIncludes": "Pro incluye:",
"usageMeter.proReformulate": "50 reformulaciones / mes",
"usageMeter.proSearch": "100 búsquedas semánticas / mes",
"usageMeter.proTags": "200 etiquetas de coche / mes",
"usageMeter.proTitles": "200 títulos de auto / mes",
"usageMeter.remaining": "{count} restantes",
"usageMeter.unlimited": "Ilimitado",
"usageMeter.upgradeDescription": "Ha utilizado todos los créditos del paquete de descubrimiento de IA. Actualice a Pro para techos más altos y funciones adicionales.",
"usageMeter.upgradePricing": "Cambiar a Pro",
"usageMeter.upgradeTitle": "Cambiar a Pro"
}

View File

@@ -0,0 +1,164 @@
{
"admin.ai.providerAnthropicOption": "🧠 Anthropic (Claude API)",
"admin.tools.brave": "Brave Search API",
"admin.users.table.subscription": "اشتراک",
"admin.users.tierUpdateFailed": "اشتراک به‌روزرسانی نشد",
"admin.users.tierUpdateSuccess": "اشتراک به {tier} به روز شد",
"agents.form.back": "برگشت",
"ai.contextSourceHeading": "منبع زمینه",
"ai.tones.academic": "دانشگاهی",
"ai.tones.casual": "گاه به گاه",
"ai.tones.creative": "خلاق",
"ai.tones.professional": "حرفه ای",
"appearance.fontInterDefault": "اینتر (پیش‌فرض)",
"billing.enterpriseTitle": "تصدی",
"brainstorm.addIdea": "ایده اضافه کنید",
"brainstorm.brainstormThisIdea": "طوفان فکری این ایده",
"brainstorm.cancel": "لغو کنید",
"brainstorm.canvasChildBranch": "کودک",
"brainstorm.canvasDoubleClickHint": "برای افزودن ایده دوبار کلیک کنید",
"brainstorm.canvasEditTitleNewIdea": "ایده جدید",
"brainstorm.canvasEditTitleReply": "پاسخ دهید",
"brainstorm.canvasPlaceholderIdea": "ایده شما…",
"brainstorm.canvasPlaceholderReply": "پاسخ شما…",
"brainstorm.canvasShortcutCancel": "لغو",
"brainstorm.canvasShortcutSave": "ذخیره کنید",
"brainstorm.canvasWaitingHint": "بوم منتظر جرقه توست...",
"brainstorm.convertedToNoteStatus": "به یادداشت تبدیل شد",
"brainstorm.converting": "در حال تبدیل...",
"brainstorm.deepen": "عمیق کنید",
"brainstorm.deepening": "در حال تولید...",
"brainstorm.delete": "حذف کنید",
"brainstorm.derived_from": "برگرفته از",
"brainstorm.dismiss": "مربوط نیست",
"notes.dismiss": "مربوط نیست",
"brainstorm.export": "صادرات",
"brainstorm.exportDefaultNoteTitle": "سنتز",
"brainstorm.exportFailedMessage": "صادرات انجام نشد",
"brainstorm.exportNotebookPrefix": "دفترچه یادداشت:",
"brainstorm.exportOpening": "باز کردن…",
"brainstorm.exporting": "در حال صادرات...",
"brainstorm.extends": "تمدید می شود",
"brainstorm.extract": "یادداشت ایجاد کنید",
"brainstorm.feedbackAlreadyPending": "یک دعوت نامه برای این شخص از قبل در انتظار است.",
"brainstorm.feedbackAlreadyShared": "این شخص قبلاً به این طوفان فکری دسترسی دارد.",
"brainstorm.feedbackGenericError": "خطا",
"brainstorm.feedbackInviteResent": "دعوت دوباره ارسال شد!",
"brainstorm.feedbackInviteSent": "دعوت نامه ارسال شد!",
"brainstorm.generating": "هوش مصنوعی در حال برداشت دانه های فکر است...",
"brainstorm.guestReadOnlyNotice": "شما در حال مشاهده این طوفان فکری به عنوان یک مهمان هستید. برای ویرایش وارد شوید",
"brainstorm.ideaDetailConnection": "اتصال",
"brainstorm.ideaDetailNovelty": "تازگی",
"brainstorm.novelty": "تازگی",
"brainstorm.ideaDetailWave": "موج",
"brainstorm.wave": "موج",
"brainstorm.ideaOrigin": "خاستگاه ایده",
"notes.ideaOrigin": "خاستگاه ایده",
"brainstorm.ideas": "ایده ها",
"brainstorm.impactNotesEnriched": "{count} یادداشت (ها) غنی شده است",
"brainstorm.impactNotesMarkedDry": "{count} یادداشت خشک علامت‌گذاری شد",
"brainstorm.invite": "دعوت کنید",
"brainstorm.legendDisruptions": "اختلالات",
"brainstorm.legendSeed": "بذر",
"brainstorm.linkCopied": "پیوند دعوت کپی شد!",
"brainstorm.linkedNotes": "یادداشت های مرتبط",
"brainstorm.liveCollaborationTitle": "همکاری زنده",
"brainstorm.liveOtherParticipants": "{count} شرکت‌کننده دیگر",
"brainstorm.liveStatus": "زندگی کنید",
"brainstorm.liveYouMarker": "(شما)",
"brainstorm.manualIdeaPrompt": "عنوان ایده شما:",
"brainstorm.newBrainstorm": "طوفان فکری جدید",
"brainstorm.noNoteLink": "ایده کاملا مولد",
"notes.noNoteLink": "ایده کاملا مولد",
"brainstorm.noSessions": "هنوز طوفان فکری وجود ندارد",
"brainstorm.none_found": "لینک یادداشت وجود ندارد",
"brainstorm.noteCreated": "یادداشت ایجاد شد",
"brainstorm.opposes": "در مخالفت با",
"brainstorm.originConnection": "اتصال مبدا",
"brainstorm.originalSeedDescription": "ایده اصلی بذر",
"brainstorm.ownerBadge": "مالک",
"brainstorm.placeholder": "مفهومی را وارد کنید تا آشکار شود...",
"brainstorm.playbackReturnToLive": "بازگشت به زندگی",
"brainstorm.playbackStep": "مرحله {current}/{total}",
"brainstorm.playbackStepsCount": "{count} مرحله",
"brainstorm.seedLabel": "ایده بذر",
"brainstorm.seedNodeBadge": "دانه",
"brainstorm.sessions": "طوفان فکری",
"brainstorm.shareDialogTitle": "طوفان فکری را به اشتراک بگذارید",
"brainstorm.shareFooterHint": "آنها اعلانی برای پذیرش یا رد دریافت خواهند کرد.",
"brainstorm.shareGuestsCanEdit": "به مهمانان اجازه ویرایش بدهید",
"brainstorm.shareNameOrEmailPlaceholder": "نام یا ایمیل…",
"brainstorm.sharePublicLink": "لینک عمومی",
"brainstorm.shareSearchLabel": "کسی را پیدا کن",
"brainstorm.shareSubmit": "به اشتراک بگذارید",
"brainstorm.shareSubmitting": "در حال ارسال…",
"brainstorm.spatialMode": "حالت کاوش فضایی",
"brainstorm.startBrainstorm": "طوفان فکری را شروع کنید",
"brainstorm.startOne": "یکی را شروع کنید",
"brainstorm.subtitle": "ابعاد پتانسیل را آشکار کنید",
"brainstorm.synthesizes": "سنتز می کند",
"brainstorm.title": "امواج فکر",
"brainstorm.toastConvertFailed": "تبدیل نشد",
"brainstorm.toastConvertSuccess": "ایده تبدیل به یادداشت شد!",
"brainstorm.toastDismissFailed": "اخراج نشد",
"brainstorm.toastDismissSuccess": "ایده رد شد",
"brainstorm.toastExpandFailed": "گسترش یافت نشد",
"brainstorm.toastExpandSuccess": "ایده ها گسترش یافت!",
"brainstorm.toastExportFailed": "صادر نشد",
"brainstorm.toastExportNoteSuccess": "به عنوان یادداشت صادر شد!",
"brainstorm.transposes": "جابجا می کند",
"brainstorm.unnamedPerson": "بدون نام",
"brainstorm.viewNote": "مشاهده یادداشت",
"brainstorm.wave1": "موج ۱",
"brainstorm.wave2": "موج ۲",
"brainstorm.wave3": "موج ۳",
"brainstorm.waveBadge": "موج {موج}",
"brainstorm.waveFlavorAnalogy": "مقایسه",
"byokSettings.alias": "برچسب (اختیاری)",
"byokSettings.aliasPlaceholder": "به عنوان مثال OpenAI کار کنید",
"byokSettings.apiKey": "کلید API",
"byokSettings.badgeActive": "BYOK فعال است",
"byokSettings.confirmDelete": "این کلید API برای همیشه حذف شود؟",
"byokSettings.deleted": "کلید API حذف شد",
"byokSettings.description": "کلیدهای ارائه‌دهنده LLM خود را برای دور زدن سهمیه‌های Discovery Pack وصل کنید. کلیدها در حالت استراحت رمزگذاری می شوند.",
"byokSettings.empty": "هنوز هیچ کلید API پیکربندی نشده است.",
"byokSettings.error": "کلید API ذخیره نشد",
"byokSettings.loadError": "کلیدهای API بارگیری نشد",
"byokSettings.loading": "در حال بارگیری کلیدها...",
"byokSettings.provider": "ارائه دهنده",
"byokSettings.providerPlaceholder": "ارائه دهنده ای را انتخاب کنید",
"byokSettings.save": "کلید ذخیره",
"byokSettings.saved": "کلید API ذخیره شد",
"byokSettings.tierRequired": "BYOK به یک طرح حرفه ای یا بالاتر نیاز دارد. برای اتصال کلیدهای API خود، ارتقا دهید.",
"byokSettings.title": "کلیدهای API شما (BYOK)",
"richTextEditor.imageUrlPlaceholder": "https://example.com/image.png",
"settings.themeBaseGroup": "پایه",
"settings.themeBlue": "آبی",
"settings.themeGreen": "سبز",
"settings.themeLavender": "اسطوخودوس",
"settings.themeMidnight": "نیمه شب",
"settings.themeOcean": "اقیانوس",
"settings.themePalettesGroup": "پالت های رنگی",
"settings.themeSand": "شن و ماسه",
"settings.themeSepia": "سپیا",
"settings.themeSunset": "غروب آفتاب",
"sidebar.sharedNotebookBadge": "· به اشتراک گذاشته شده",
"sidebar.sortAlpha": "A → Z",
"usageMeter.addApiKey": "از کلید API خود (BYOK) استفاده کنید",
"usageMeter.featureSearch": "جستجو کنید",
"usageMeter.featureTags": "برچسب ها",
"usageMeter.featureTitles": "عناوین",
"usageMeter.later": "بعدا",
"usageMeter.packName": "بسته کشف هوش مصنوعی",
"usageMeter.proChat": "۱۰۰ پیام چت در ماه",
"usageMeter.proIncludes": "حرفه ای شامل:",
"usageMeter.proReformulate": "۵۰ فرمول مجدد در ماه",
"usageMeter.proSearch": "۱۰۰ جستجوی معنایی در ماه",
"usageMeter.proTags": "۲۰۰ برچسب خودکار در ماه",
"usageMeter.proTitles": "۲۰۰ عنوان خودکار در ماه",
"usageMeter.remaining": "{count} باقی مانده است",
"usageMeter.unlimited": "نامحدود",
"usageMeter.upgradeDescription": "شما از تمام اعتبارات AI Discovery Pack خود استفاده کرده اید. برای محدودیت های بالاتر و ویژگی های اضافی به Pro ارتقا دهید.",
"usageMeter.upgradePricing": "به Pro ارتقا دهید",
"usageMeter.upgradeTitle": "به Pro ارتقا دهید"
}

View File

@@ -0,0 +1,359 @@
#!/usr/bin/env node
/**
* Builds es.json, it.json, pt.json i18n overrides from FR reference strings.
* Keys: locale still matches EN but FR differs (+ 11 mandatory keys).
*/
import fs from 'fs'
import path from 'path'
import { fileURLToPath } from 'url'
import https from 'https'
const __dirname = path.dirname(fileURLToPath(import.meta.url))
const localesDir = path.join(__dirname, '../../locales')
const outDir = __dirname
function flat(obj, prefix = '') {
const result = {}
for (const [k, v] of Object.entries(obj)) {
const key = prefix ? `${prefix}.${k}` : k
if (v && typeof v === 'object' && !Array.isArray(v)) Object.assign(result, flat(v, key))
else result[key] = v
}
return result
}
const MANDATORY = [
'ai.featureLocked',
'ai.quotaExceeded',
'profile.tab',
'about.tab',
'appearance.tab',
'billing.tab',
'usageMeter.featureChat',
'usageMeter.featureReformulate',
'usageMeter.featureBrainstormCreate',
'usageMeter.featureBrainstormExpand',
'usageMeter.featureBrainstormEnrich',
]
const LANG_MAP = {
es: 'es',
it: 'it',
pt: 'pt',
nl: 'nl',
pl: 'pl',
ru: 'ru',
ar: 'ar',
}
function worklistKeys(lang) {
const en = flat(JSON.parse(fs.readFileSync(path.join(localesDir, 'en.json'), 'utf8')))
const loc = flat(JSON.parse(fs.readFileSync(path.join(localesDir, `${lang}.json`), 'utf8')))
const fr = flat(JSON.parse(fs.readFileSync(path.join(localesDir, 'fr.json'), 'utf8')))
const keys = Object.keys(en).filter((k) => loc[k] === en[k] && fr[k] && fr[k] !== en[k])
for (const k of MANDATORY) {
if (fr[k] && !keys.includes(k)) keys.push(k)
}
return keys.sort()
}
/** Protect ICU-style placeholders during translation */
function shieldPlaceholders(text) {
const tokens = []
const shielded = text.replace(/\{[^}]+\}/g, (m) => {
const id = `__PH_${tokens.length}__`
tokens.push(m)
return id
})
return { shielded, tokens }
}
function unshieldPlaceholders(text, tokens) {
let out = text
tokens.forEach((tok, i) => {
out = out.replace(`__PH_${i}__`, tok)
out = out.replace(`__ PH _ ${i} __`, tok)
out = out.replace(new RegExp(`__\\s*PH\\s*_\\s*${i}\\s*__`, 'gi'), tok)
})
return out
}
function myMemoryTranslate(text, targetLang, attempt = 0) {
return new Promise((resolve, reject) => {
const { shielded, tokens } = shieldPlaceholders(text)
const q = encodeURIComponent(shielded.slice(0, 4500))
const url = `https://api.mymemory.translated.net/get?q=${q}&langpair=fr|${targetLang}`
https
.get(url, (res) => {
let body = ''
res.on('data', (c) => (body += c))
res.on('end', () => {
try {
const data = JSON.parse(body)
if (data.responseStatus === 200 && data.responseData?.translatedText) {
resolve(unshieldPlaceholders(data.responseData.translatedText, tokens))
} else if (attempt < 4) {
setTimeout(() => {
myMemoryTranslate(text, targetLang, attempt + 1)
.then(resolve)
.catch(reject)
}, 1500 * (attempt + 1))
} else {
reject(new Error(data.responseDetails || 'translate failed'))
}
} catch (e) {
reject(e)
}
})
})
.on('error', reject)
})
}
async function translateFr(text, targetLang) {
if (!text || !text.trim()) return text
return myMemoryTranslate(text, targetLang)
}
const MANUAL = {
es: {
'sidebar.sortAlpha': 'Orden A → Z',
'settings.cardSizeVariable': 'Tamaños variables (pequeño/mediano/grande)',
'brainstorm.aiIdea': 'IA',
'brainstorm.seedNodeBadge': 'SEMILLA',
'byokSettings.badgeActive': 'BYOK activo',
'aiSettings.title': 'IA',
'aiSettings.providerOllama': 'Ollama (local)',
'admin.ai.providerOllamaOption': '🦙 Ollama (local y gratuito)',
'admin.ai.providerLMStudioOption': '🖥️ LM Studio (local)',
'usageMeter.packName': 'Pack descubrimiento IA',
'landing.pricing.perUser': '+ 3,90€/usuario',
'landing.pricing.perUserAnnual': '+ 2,90€/usuario, facturación anual',
'ai.featureLocked':
'Esta función requiere el plan PRO o superior.',
'ai.quotaExceeded': 'Límite mensual alcanzado. Se restablece el próximo mes.',
'profile.tab': 'Perfil',
'about.tab': 'Acerca de',
'appearance.tab': 'Apariencia',
'billing.tab': 'Facturación',
'usageMeter.featureChat': 'Mensajes IA',
'usageMeter.featureReformulate': 'Reformulaciones',
'usageMeter.featureBrainstormCreate': 'Creaciones de brainstorm',
'usageMeter.featureBrainstormExpand': 'Expansiones de brainstorm',
'usageMeter.featureBrainstormEnrich': 'Enriquecimientos de brainstorm',
},
it: {
'sidebar.sortAlpha': 'Ordine A → Z',
'settings.cardSizeVariable': 'Dimensioni variabili (small/medium/large)',
'brainstorm.aiIdea': 'IA',
'brainstorm.seedNodeBadge': 'SEME',
'byokSettings.badgeActive': 'BYOK attivo',
'aiSettings.title': 'IA',
'aiSettings.providerOllama': 'Ollama (locale)',
'admin.ai.providerOllamaOption': '🦙 Ollama (locale e gratuito)',
'admin.ai.providerLMStudioOption': '🖥️ LM Studio (locale)',
'usageMeter.packName': 'Pacchetto scoperta IA',
'landing.pricing.perUser': '+ 3,90€/utente',
'landing.pricing.perUserAnnual': '+ 2,90€/utente, fatturazione annuale',
'auth.email': 'Email',
'ai.featureLocked':
'Questa funzione richiede il piano PRO o superiore.',
'ai.quotaExceeded': 'Limite mensile raggiunto. Si azzera il mese prossimo.',
'profile.tab': 'Profilo',
'about.tab': 'Informazioni',
'appearance.tab': 'Aspetto',
'billing.tab': 'Fatturazione',
'usageMeter.featureChat': 'Messaggi IA',
'usageMeter.featureReformulate': 'Riformulazioni',
'usageMeter.featureBrainstormCreate': 'Creazioni brainstorm',
'usageMeter.featureBrainstormExpand': 'Espansioni brainstorm',
'usageMeter.featureBrainstormEnrich': 'Arricchimenti brainstorm',
},
pt: {
'sidebar.sortAlpha': 'Ordenação A → Z',
'settings.cardSizeVariable': 'Tamanhos variáveis (pequeno/médio/grande)',
'brainstorm.aiIdea': 'IA',
'brainstorm.seedNodeBadge': 'SEMENTE',
'byokSettings.badgeActive': 'BYOK ativo',
'aiSettings.title': 'IA',
'aiSettings.providerOllama': 'Ollama (local)',
'admin.ai.providerOllamaOption': '🦙 Ollama (local e gratuito)',
'admin.ai.providerLMStudioOption': '🖥️ LM Studio (local)',
'usageMeter.packName': 'Pack descoberta IA',
'landing.pricing.perUser': '+ 3,90€/utilizador',
'landing.pricing.perUserAnnual': '+ 2,90€/utilizador, faturação anual',
'ai.featureLocked':
'Esta funcionalidade requer o plano PRO ou superior.',
'ai.quotaExceeded': 'Limite mensal atingido. Repõe-se no próximo mês.',
'profile.tab': 'Perfil',
'about.tab': 'Sobre',
'appearance.tab': 'Aparência',
'billing.tab': 'Faturação',
'usageMeter.featureChat': 'Mensagens IA',
'usageMeter.featureReformulate': 'Reformulações',
'usageMeter.featureBrainstormCreate': 'Criações de brainstorm',
'usageMeter.featureBrainstormExpand': 'Expansões de brainstorm',
'usageMeter.featureBrainstormEnrich': 'Enriquecimentos de brainstorm',
},
nl: {
'sidebar.sortAlpha': 'Sortering A → Z',
'brainstorm.aiIdea': 'AI',
'brainstorm.seedNodeBadge': 'ZAAD',
'byokSettings.badgeActive': 'BYOK actief',
'aiSettings.title': 'AI',
'usageMeter.remaining': '{count} resterend',
'brainstorm.liveOtherParticipants': '{count} andere deelnemers',
'brainstorm.playbackStep': 'Stap {current}/{total}',
'brainstorm.playbackStepsCount': '{count} stappen',
'brainstorm.waveBadge': 'Golf {wave}',
'landing.pricing.perUser': '+ 3,90€/gebruiker',
'landing.pricing.perUserAnnual': '+ 2,90€/gebruiker, jaarlijks gefactureerd',
'ai.featureLocked': 'Deze functie vereist het PRO-abonnement of hoger.',
'ai.quotaExceeded': 'Maandelijkse limiet bereikt. Reset volgende maand.',
'profile.tab': 'Profiel',
'about.tab': 'Over',
'appearance.tab': 'Weergave',
'billing.tab': 'Facturering',
'usageMeter.featureChat': 'AI-berichten',
'usageMeter.featureReformulate': 'Herschrijvingen',
'usageMeter.featureBrainstormCreate': 'Brainstorm-aanmaak',
'usageMeter.featureBrainstormExpand': 'Brainstorm-uitbreidingen',
'usageMeter.featureBrainstormEnrich': 'Brainstorm-verrijkingen',
},
pl: {
'sidebar.sortAlpha': 'Sortowanie A → Z',
'brainstorm.aiIdea': 'AI',
'brainstorm.seedNodeBadge': 'NASIONO',
'byokSettings.badgeActive': 'BYOK aktywny',
'aiSettings.title': 'AI',
'usageMeter.remaining': 'Pozostało: {count}',
'brainstorm.liveOtherParticipants': '{count} innych uczestników',
'brainstorm.playbackStep': 'Krok {current}/{total}',
'brainstorm.playbackStepsCount': '{count} kroków',
'brainstorm.waveBadge': 'Fala {wave}',
'landing.pricing.perUser': '+ 3,90€/użytkownika',
'landing.pricing.perUserAnnual': '+ 2,90€/użytkownika, rozliczenie roczne',
'ai.featureLocked': 'Ta funkcja wymaga planu PRO lub wyższego.',
'ai.quotaExceeded': 'Osiągnięto limit miesięczny. Reset w przyszłym miesiącu.',
'profile.tab': 'Profil',
'about.tab': 'O aplikacji',
'appearance.tab': 'Wygląd',
'billing.tab': 'Rozliczenia',
'usageMeter.featureChat': 'Wiadomości AI',
'usageMeter.featureReformulate': 'Przeformułowania',
'usageMeter.featureBrainstormCreate': 'Tworzenia brainstorm',
'usageMeter.featureBrainstormExpand': 'Rozszerzenia brainstorm',
'usageMeter.featureBrainstormEnrich': 'Wzbogacenia brainstorm',
},
ru: {
'sidebar.sortAlpha': 'Сортировка A → Z',
'brainstorm.aiIdea': 'ИИ',
'brainstorm.seedNodeBadge': 'СЕМЯ',
'byokSettings.badgeActive': 'BYOK активен',
'aiSettings.title': 'ИИ',
'usageMeter.remaining': 'осталось {count}',
'brainstorm.liveOtherParticipants': '{count} других участников',
'brainstorm.playbackStep': 'Шаг {current}/{total}',
'brainstorm.playbackStepsCount': '{count} шагов',
'brainstorm.waveBadge': 'Волна {wave}',
'landing.pricing.perUser': '+ 3,90€/пользователь',
'landing.pricing.perUserAnnual': '+ 2,90€/пользователь, ежегодная оплата',
'ai.featureLocked': 'Эта функция требует тарифа PRO или выше.',
'ai.quotaExceeded': 'Достигнут месячный лимит. Сброс в следующем месяце.',
'profile.tab': 'Профиль',
'about.tab': 'О приложении',
'appearance.tab': 'Оформление',
'billing.tab': 'Оплата',
'usageMeter.featureChat': 'Сообщения ИИ',
'usageMeter.featureReformulate': 'Переформулировки',
'usageMeter.featureBrainstormCreate': 'Создания brainstorm',
'usageMeter.featureBrainstormExpand': 'Расширения brainstorm',
'usageMeter.featureBrainstormEnrich': 'Обогащения brainstorm',
},
ar: {
'brainstorm.aiIdea': 'ذكاء اصطناعي',
'brainstorm.seedNodeBadge': 'بذرة',
'byokSettings.badgeActive': 'BYOK نشط',
'usageMeter.remaining': '{count} متبقي',
'brainstorm.liveOtherParticipants': '{count} مشاركين آخرين',
'brainstorm.playbackStep': 'الخطوة {current}/{total}',
'brainstorm.playbackStepsCount': '{count} خطوات',
'brainstorm.waveBadge': 'موجة {wave}',
'landing.pricing.perUser': '+ 3,90€/مستخدم',
'landing.pricing.perUserAnnual': '+ 3,90€/مستخدم، فوترة سنوية',
'ai.featureLocked': 'تتطلب هذه الميزة خطة PRO أو أعلى.',
'ai.quotaExceeded': 'تم الوصول إلى الحد الشهري. يُعاد التعيين الشهر القادم.',
'profile.tab': 'الملف الشخصي',
'about.tab': 'حول',
'appearance.tab': 'المظهر',
'billing.tab': 'الفوترة',
'usageMeter.featureChat': 'رسائل الذكاء الاصطناعي',
'usageMeter.featureReformulate': 'إعادة الصياغة',
'usageMeter.featureBrainstormCreate': 'إنشاءات العصف الذهني',
'usageMeter.featureBrainstormExpand': 'توسعات العصف الذهني',
'usageMeter.featureBrainstormEnrich': 'إثراءات العصف الذهني',
},
}
const sleep = (ms) => new Promise((r) => setTimeout(r, ms))
async function buildLang(lang) {
const fr = flat(JSON.parse(fs.readFileSync(path.join(localesDir, 'fr.json'), 'utf8')))
const keys = worklistKeys(lang)
const target = LANG_MAP[lang]
const outFile = path.join(outDir, `${lang}.json`)
const out = fs.existsSync(outFile)
? JSON.parse(fs.readFileSync(outFile, 'utf8'))
: {}
const frCache = new Map()
console.error(`[${lang}] ${keys.length} keys`)
for (let i = 0; i < keys.length; i++) {
const key = keys[i]
if (MANUAL[lang]?.[key]) {
out[key] = MANUAL[lang][key]
continue
}
// Re-translate if placeholders were corrupted (non-ASCII inside braces)
const existing = out[key]
if (existing && /\{[^}]*[^\x00-\x7F][^}]*\}/.test(existing)) {
delete out[key]
}
const frText = fr[key]
if (!frText) {
console.error(` skip missing fr: ${key}`)
continue
}
const existingAfter = out[key]
if (existingAfter && existingAfter !== frText) {
continue
}
let translated
if (frCache.has(frText)) {
translated = frCache.get(frText)
} else {
try {
translated = await translateFr(frText, target)
frCache.set(frText, translated)
await sleep(350)
} catch (e) {
console.error(` FAIL ${key}:`, e.message)
translated = frText
}
}
out[key] = translated
if ((i + 1) % 50 === 0) console.error(` ${i + 1}/${keys.length}`)
}
const file = path.join(outDir, `${lang}.json`)
fs.writeFileSync(file, JSON.stringify(out, null, 2) + '\n', 'utf8')
console.error(`Wrote ${file} (${Object.keys(out).length} keys)`)
}
const langs = process.argv.slice(2)
const targets = langs.length ? langs : ['es', 'it', 'pt']
for (const lang of targets) {
await buildLang(lang)
}

View File

@@ -0,0 +1,358 @@
{
"about.tab": "के बारे में",
"about.technology.ai": "AI",
"aiSettings.title": "ऐ",
"about.technology.ui": "UI",
"admin.ai.providerCustomOption": "🔧 कस्टम ओपनएआई-संगत",
"admin.ai.providerOllamaOption": "🦙 ओलामा (स्थानीय और मुफ़्त)",
"admin.chat": "एआई चैट",
"admin.email.activeAuto": "ऑटो मोड: पहले पुनः भेजें का उपयोग किया जाएगा, फ़ॉलबैक के रूप में SMTP का उपयोग किया जाएगा।",
"admin.email.activeProvider": "सक्रिय प्रदाता",
"admin.email.activeSmtp": "ऑटो मोड: एसएमटीपी का उपयोग किया जाएगा (पुनः भेजें कॉन्फ़िगर नहीं)।",
"admin.email.keySet": "कुंजी विन्यस्त",
"admin.email.noneConfigured": "कोई ईमेल सेवा कॉन्फ़िगर नहीं की गई. पुनः भेजें या SMTP सेट करें.",
"admin.email.status": "सेवा स्थिति",
"admin.email.testFail": "परीक्षण विफल रहा",
"admin.email.testOk": "परीक्षण उत्तीर्ण",
"admin.lab": "लैब",
"admin.tools.brave": "बहादुर खोज एपीआई",
"admin.tools.searxngUrl": "SearXNG यूआरएल",
"admin.users.confirmDelete": "क्या आपको यकीन है? इस एक्शन को वापस नहीं किया जा सकता।",
"admin.users.table.subscription": "सदस्यता",
"admin.users.tierUpdateFailed": "सदस्यता अद्यतन करने में विफल",
"admin.users.tierUpdateSuccess": "सदस्यता को {स्तर} तक अपडेट किया गया",
"admin.workspace": "कार्यस्थान",
"agents.filterAll": "सभी",
"agents.form.back": "पीछे",
"agents.form.includeImages": "छवियाँ शामिल करें",
"agents.form.includeImagesHint": "स्क्रैप किए गए पृष्ठों से छवियां निकालें और उन्हें जेनरेट किए गए नोट के साथ संलग्न करें",
"agents.help.advancedContent": "अतिरिक्त सेटिंग्स तक पहुंचने के लिए फॉर्म के नीचे **\"उन्नत मोड\"** पर क्लिक करें।\n\n### एआई निर्देश\n\nयह फ़ील्ड आपको एजेंट के लिए **डिफ़ॉल्ट सिस्टम प्रॉम्प्ट को बदलने** की सुविधा देता है। यदि खाली छोड़ दिया जाता है, तो एजेंट अपने प्रकार के अनुसार अनुकूलित एक स्वचालित प्रॉम्प्ट का उपयोग करता है।\n\n**इसका उपयोग क्यों करें?** आप यह नियंत्रित करना चाहते हैं कि एजेंट कैसा व्यवहार करता है। उदाहरण के लिए:\n- \"सारांश अंग्रेजी में लिखें, भले ही स्रोत फ़्रेंच में हों\"\n- \"नोट को अनुभागों के साथ संरचित करें: संदर्भ, मुख्य बिंदु, व्यक्तिगत राय\"\n- \"30 दिन से अधिक पुराने लेखों पर ध्यान न दें और नवीनतम समाचारों पर ध्यान केंद्रित करें\"\n- \"प्रत्येक खोजे गए विषय के लिए, लिंक के साथ 3 अनुवर्ती लीड सुझाएं\"\n\n> **ध्यान दें:** आपके निर्देश डिफ़ॉल्ट को प्रतिस्थापित करते हैं, वे उनमें जुड़ते नहीं हैं।\n\n### अधिकतम पुनरावृत्तियाँ\n\nयह **चक्रों की अधिकतम संख्या** है जिसे एजेंट निष्पादित कर सकता है। एक चक्र = एजेंट सोचता है, एक उपकरण को कॉल करता है, परिणाम पढ़ता है, फिर अगली कार्रवाई का निर्णय लेता है।\n\n- **3-5 पुनरावृत्तियाँ:** सरल कार्यों के लिए (एक पृष्ठ को स्क्रैप करना)\n- **10 पुनरावृत्तियाँ (डिफ़ॉल्ट):** अधिकांश मामलों के लिए अच्छा संतुलन\n- **15-25 पुनरावृत्तियाँ:** गहन अनुसंधान के लिए जहां एजेंट को कई सुरागों का पता लगाने की आवश्यकता होती है\n\n> **चेतावनी:** अधिक पुनरावृत्तियाँ = अधिक समय और संभावित रूप से उच्च एपीआई लागत।",
"agents.help.frequencyContent": "| आवृत्ति | व्यवहार\n|----|-------\n| **मैनुअल** | आप स्वयं \"रन\" पर क्लिक करें - कोई स्वचालित शेड्यूलिंग नहीं\n| **प्रति घंटा** | हर घंटे चलता है\n| **दैनिक** | प्रति दिन एक बार चलता है\n| **साप्ताहिक** | प्रति सप्ताह एक बार चलता है\n| **मासिक** | प्रति माह एक बार चलता है\n\n> **टिप:** अपने एजेंट का परीक्षण करने के लिए \"मैनुअल\" से शुरुआत करें, फिर परिणामों से संतुष्ट होने पर स्वचालित आवृत्ति पर स्विच करें।",
"agents.help.howToUseContent": "1. **\"नया एजेंट\"** पर क्लिक करें (या पृष्ठ के नीचे **टेम्पलेट** से प्रारंभ करें)\n2. एक **एजेंट प्रकार** चुनें (शोधकर्ता, मॉनिटर, पर्यवेक्षक, कस्टम)\n3. इसे **नाम** दें और प्रकार-विशिष्ट फ़ील्ड भरें\n4. वैकल्पिक रूप से एक **लक्ष्य नोटबुक** चुनें जहां परिणाम सहेजे जाएंगे\n5. एक **आवृत्ति** चुनें (मैनुअल = आप इसे स्वयं ट्रिगर करें)\n6. **बनाएं** पर क्लिक करें, फिर एजेंट कार्ड पर **रन** बटन दबाएं\n7. एक बार समाप्त होने पर, आपके लक्ष्य नोटबुक में एक नया नोट दिखाई देता है",
"agents.help.targetNotebookContent": "जब कोई एजेंट अपना कार्य पूरा कर लेता है, तो वह **एक नोट बनाता है**। **लक्ष्य नोटबुक** निर्धारित करती है कि वह नोट कहाँ जाएगा:\n\n- **इनबॉक्स** (डिफ़ॉल्ट) - नोट आपके सामान्य नोट्स में चला जाता है\n- **विशिष्ट नोटबुक** — एजेंट परिणामों को व्यवस्थित रखने के लिए एक नोटबुक चुनें\n\n> **टिप:** सभी स्वचालित सामग्री को एक ही स्थान पर रखने के लिए \"एजेंट रिपोर्ट\" जैसी एक समर्पित नोटबुक बनाएं।",
"agents.newBadge": "नया",
"agents.noResults": "कोई भी एजेंट आपकी खोज से मेल नहीं खाता.",
"agents.schedule.dayOfMonth": "महीने का दिन",
"agents.schedule.dayOfWeek": "सप्ताह का दिन",
"agents.schedule.days.fri": "शुक्रवार",
"agents.schedule.days.mon": "सोमवार",
"agents.schedule.days.sat": "शनिवार",
"agents.schedule.days.sun": "रविवार",
"agents.schedule.days.thu": "गुरुवार",
"agents.schedule.days.tue": "मंगलवार",
"agents.schedule.days.wed": "बुधवार",
"agents.schedule.nextRun": "अगला भाग",
"agents.schedule.pending": "लंबित ट्रिगर",
"agents.schedule.time": "समय",
"agents.searchPlaceholder": "खोज एजेंट...",
"agents.toasts.autoRunError": "एजेंट \"{नाम}\" स्वचालित निष्पादन के दौरान विफल रहा",
"agents.toasts.autoRunSuccess": "एजेंट \"{नाम}\" सफलता के साथ स्वचालित रूप से निष्पादित हुआ",
"ai.action.describeImages": "छवियों का वर्णन करें",
"ai.contextSourceHeading": "प्रसंग स्रोत",
"ai.featureLocked": "इस सुविधा के लिए PRO योजना या उच्चतर की आवश्यकता होती है।",
"ai.generateTitleFromImage": "छवि से शीर्षक उत्पन्न करें",
"notes.generateTitleFromImage": "छवि से शीर्षक उत्पन्न करें",
"ai.noImagesError": "इस नोट में कोई चित्र नहीं",
"ai.overview": "सिंहावलोकन",
"ai.quotaExceeded": "मासिक सीमा पूरी हो गई. अगले महीने रीसेट होगा.",
"ai.titleGenerated": "छवि से उत्पन्न शीर्षक",
"ai.tones.academic": "अकादमिक",
"ai.tones.casual": "अनौपचारिक",
"ai.tones.creative": "रचनात्मक",
"ai.tones.professional": "पेशेवर",
"appearance.fontInterDefault": "इंटर (डिफ़ॉल्ट)",
"appearance.selectTheme": "थीम चुनें",
"appearance.tab": "उपस्थिति",
"auth.signOut": "साइन आउट",
"billing.businessAnnualPrice": "€299",
"billing.businessPrice": "€29.90",
"billing.enterpriseTitle": "उद्यम",
"billing.proAnnualPrice": "€99",
"billing.proPrice": "€9.90",
"billing.tab": "बिलिंग",
"brainstorm.addIdea": "विचार जोड़ें",
"brainstorm.brainstormThisIdea": "इस विचार पर मंथन करें",
"brainstorm.cancel": "रद्द करना",
"brainstorm.canvasChildBranch": "बच्चा",
"brainstorm.canvasDoubleClickHint": "कोई विचार जोड़ने के लिए डबल-क्लिक करें",
"brainstorm.canvasEditTitleNewIdea": "नया विचार",
"brainstorm.canvasEditTitleReply": "जवाब",
"brainstorm.canvasPlaceholderIdea": "आपका विचार...",
"brainstorm.canvasPlaceholderReply": "आपके उत्तर…",
"brainstorm.canvasShortcutCancel": "रद्द करना",
"brainstorm.canvasShortcutSave": "बचाना",
"brainstorm.canvasWaitingHint": "कैनवास आपकी चिंगारी की प्रतीक्षा कर रहा है...",
"brainstorm.convertedToNoteStatus": "नोट में परिवर्तित किया गया",
"brainstorm.converting": "परिवर्तित किया जा रहा है...",
"brainstorm.deepen": "गहरा",
"brainstorm.deepening": "उत्पन्न हो रहा है...",
"brainstorm.delete": "मिटाना",
"labels.delete": "मिटाना",
"brainstorm.derived_from": "से व्युत्पन्न",
"brainstorm.dismiss": "प्रासंगिक नहीं",
"notes.dismiss": "प्रासंगिक नहीं",
"brainstorm.export": "निर्यात",
"brainstorm.exportDefaultNoteTitle": "संश्लेषण",
"brainstorm.exportFailedMessage": "निर्यात विफल",
"brainstorm.exportNotebookPrefix": "स्मरण पुस्तक:",
"brainstorm.exportOpening": "खुल रहा है...",
"brainstorm.exporting": "निर्यात किया जा रहा है...",
"brainstorm.extends": "का विस्तार",
"brainstorm.extract": "नोट बनाएँ",
"brainstorm.feedbackAlreadyPending": "इस व्यक्ति के लिए निमंत्रण पहले से ही लंबित है.",
"brainstorm.feedbackAlreadyShared": "इस व्यक्ति के पास पहले से ही इस विचार-मंथन तक पहुंच है।",
"brainstorm.feedbackGenericError": "गलती",
"diagnostics.errorStatus": "गलती",
"brainstorm.feedbackInviteResent": "निमंत्रण पुनः भेजा गया!",
"brainstorm.feedbackInviteSent": "निमंत्रण भेजा गया!",
"brainstorm.generating": "एआई विचार के बीज काट रहा है...",
"brainstorm.guestReadOnlyNotice": "आप इस मंथन को एक अतिथि के रूप में देख रहे हैं। संपादित करने के लिए साइन इन करें.",
"brainstorm.ideaDetailConnection": "संबंध",
"brainstorm.ideaDetailNovelty": "नवीनता",
"brainstorm.novelty": "नवीनता",
"brainstorm.ideaDetailWave": "लहर",
"brainstorm.wave": "लहर",
"brainstorm.ideaOrigin": "विचार की उत्पत्ति",
"notes.ideaOrigin": "विचार की उत्पत्ति",
"brainstorm.ideas": "विचारों",
"brainstorm.impactNotesEnriched": "{गिनती} नोट समृद्ध हुए",
"brainstorm.impactNotesMarkedDry": "{गिनती} नोट(नोटों) को सूखा चिह्नित किया गया",
"brainstorm.invite": "आमंत्रित करना",
"collaboration.invite": "आमंत्रित करना",
"brainstorm.legendDisruptions": "अवरोधों",
"brainstorm.legendSeed": "बीज",
"brainstorm.linkCopied": "आमंत्रण लिंक कॉपी किया गया!",
"brainstorm.linkedNotes": "जुड़े हुए नोट्स",
"brainstorm.liveCollaborationTitle": "लाइव सहयोग",
"brainstorm.liveOtherParticipants": "अन्य प्रतिभागियों की गिनती करें",
"brainstorm.liveStatus": "रहना",
"brainstorm.liveYouMarker": "(आप)",
"brainstorm.manualIdeaPrompt": "आपके विचार का शीर्षक:",
"brainstorm.newBrainstorm": "नया मंथन",
"brainstorm.noNoteLink": "विशुद्ध रूप से उत्पादक विचार",
"notes.noNoteLink": "विशुद्ध रूप से उत्पादक विचार",
"brainstorm.noSessions": "अभी तक कोई मंथन नहीं हुआ",
"brainstorm.none_found": "कोई नोट लिंक नहीं",
"brainstorm.noteCreated": "नोट बनाया गया",
"brainstorm.opposes": "के विरोध में",
"brainstorm.originConnection": "मूल संबंध",
"brainstorm.originalSeedDescription": "मूल बीज विचार",
"brainstorm.ownerBadge": "मालिक",
"collaboration.owner": "मालिक",
"brainstorm.placeholder": "प्रकट करने के लिए एक अवधारणा दर्ज करें...",
"brainstorm.playbackReturnToLive": "जीने के लिए वापस लौटें",
"brainstorm.playbackStep": "चरण {वर्तमान}/{कुल}",
"brainstorm.playbackStepsCount": "{गिनती} कदम",
"brainstorm.seedLabel": "बीज विचार",
"brainstorm.seedNodeBadge": "बीज",
"brainstorm.sessions": "मंथन",
"brainstorm.shareDialogTitle": "मंथन साझा करें",
"brainstorm.shareFooterHint": "उन्हें स्वीकार या अस्वीकार करने की सूचना मिलेगी।",
"brainstorm.shareGuestsCanEdit": "मेहमानों को संपादित करने की अनुमति दें",
"brainstorm.shareNameOrEmailPlaceholder": "नाम या ईमेल...",
"brainstorm.sharePublicLink": "सार्वजनिक लिंक",
"brainstorm.shareSearchLabel": "किसी को ढूँढें",
"brainstorm.shareSubmit": "शेयर करना",
"brainstorm.shareSubmitting": "भेजा जा रहा है...",
"brainstorm.spatialMode": "स्थानिक अन्वेषण मोड",
"brainstorm.startBrainstorm": "मंथन शुरू करें",
"brainstorm.startOne": "एक शुरू करो",
"brainstorm.subtitle": "संभावनाओं के आयाम उजागर करें",
"brainstorm.synthesizes": "संश्लेषित",
"brainstorm.title": "विचार की लहरें",
"brainstorm.toastConvertFailed": "परिवर्तित करने में विफल",
"brainstorm.toastConvertSuccess": "आइडिया नोट में बदला!",
"brainstorm.toastDismissFailed": "ख़ारिज करने में विफल",
"brainstorm.toastDismissSuccess": "आइडिया खारिज",
"brainstorm.toastExpandFailed": "विस्तार करने में विफल",
"brainstorm.toastExpandSuccess": "विचारों का विस्तार हुआ!",
"brainstorm.toastExportFailed": "निर्यात करने में विफल",
"brainstorm.toastExportNoteSuccess": "नोट के रूप में निर्यात किया गया!",
"brainstorm.transposes": "स्थानान्तरण",
"brainstorm.unnamedPerson": "कोई नाम नहीं",
"brainstorm.viewNote": "नोट देखें",
"brainstorm.wave1": "लहर 1",
"brainstorm.wave2": "तरंग 2",
"brainstorm.wave3": "तरंग 3",
"brainstorm.waveBadge": "लहर",
"brainstorm.waveFlavorAnalogy": "समानता",
"byokSettings.alias": "लेबल (वैकल्पिक)",
"byokSettings.aliasPlaceholder": "जैसे ओपनएआई कार्य करें",
"byokSettings.apiKey": "एपीआई कुंजी",
"byokSettings.badgeActive": "BYOK सक्रिय",
"byokSettings.confirmDelete": "क्या आप इस एपीआई कुंजी को स्थायी रूप से हटा देंगे?",
"byokSettings.deleted": "एपीआई कुंजी हटा दी गई",
"byokSettings.description": "डिस्कवरी पैक कोटा को बायपास करने के लिए अपनी स्वयं की एलएलएम प्रदाता कुंजियाँ कनेक्ट करें। कुंजियाँ आराम से एन्क्रिप्ट की गई हैं।",
"byokSettings.empty": "अभी तक कोई API कुंजी कॉन्फ़िगर नहीं की गई है.",
"byokSettings.error": "एपीआई कुंजी सहेजी नहीं जा सकी",
"byokSettings.loadError": "एपीआई कुंजियाँ लोड नहीं हो सकीं",
"byokSettings.loading": "कुंजियाँ लोड हो रही हैं...",
"byokSettings.provider": "प्रदाता",
"byokSettings.providerPlaceholder": "एक प्रदाता चुनें",
"byokSettings.save": "कुंजी सहेजें",
"byokSettings.saved": "एपीआई कुंजी सहेजी गई",
"byokSettings.tierRequired": "BYOK को प्रो प्लान या उच्चतर की आवश्यकता है। अपनी एपीआई कुंजियाँ कनेक्ट करने के लिए अपग्रेड करें।",
"byokSettings.title": "आपकी एपीआई कुंजियाँ (BYOK)",
"chat.timeoutWarning": "प्रतिक्रिया में अपेक्षा से अधिक समय लग रहा है...",
"collaboration.accessRevoked": "प्रवेश निरस्त कर दिया गया है",
"collaboration.addCollaborator": "सहयोगी जोड़ें",
"collaboration.addCollaboratorDescription": "इस नोट पर सहयोग करने के लिए लोगों को उनके ईमेल पते से जोड़ें।",
"collaboration.alreadyInList": "यह ईमेल पहले से ही सूची में है",
"collaboration.canEdit": "संपादित कर सकते हैं",
"collaboration.canView": "देख सकते हैं",
"collaboration.done": "हो गया",
"collaboration.emailAddress": "मेल पता",
"collaboration.emailPlaceholder": "ईमेल पता दर्ज करें",
"collaboration.enterEmailAddress": "ईमेल पता दर्ज करें",
"collaboration.errorLoading": "सहयोगियों को लोड करने में त्रुटि",
"collaboration.failedToAdd": "सहयोगी जोड़ने में विफल",
"collaboration.failedToRemove": "सहयोगी को हटाने में विफल",
"collaboration.noCollaborators": "अभी तक कोई सहयोगी नहीं. ऊपर किसी को जोड़ें!",
"collaboration.noCollaboratorsViewer": "अभी तक कोई सहयोगी नहीं.",
"collaboration.nowHasAccess": "{नाम} के पास अब इस नोट तक पहुंच है",
"collaboration.pending": "लंबित",
"collaboration.pendingInvite": "लंबित आमंत्रण",
"collaboration.peopleWithAccess": "पहुंच वाले लोग",
"collaboration.remove": "निकालना",
"collaboration.removeCollaborator": "सहयोगी को हटाएँ",
"collaboration.shareNote": "नोट साझा करें",
"collaboration.shareWithCollaborators": "सहयोगियों के साथ साझा करें",
"collaboration.unnamedUser": "अनाम उपयोगकर्ता",
"collaboration.viewerDescription": "आपके पास इस नोट तक पहुंच है. केवल स्वामी ही सहयोगियों को प्रबंधित कर सकता है.",
"collaboration.willBeAdded": "नोट बनाते समय {ईमेल} को सहयोगी के रूप में जोड़ा जाएगा",
"dataManagement.title": "डेटा",
"diagnostics.checking": "जाँच हो रही है...",
"diagnostics.description": "अपने AI प्रदाता कनेक्शन स्थिति की जाँच करें",
"diagnostics.operational": "आपरेशनल",
"general.clean": "साफ",
"general.indexAll": "सभी को अनुक्रमित करें",
"general.testConnection": "परीक्षण कनेक्शन",
"generalSettings.title": "सामान्य",
"labHeader.rename": "नाम बदलें",
"labels.addLabel": "लेबल जोड़ें",
"labels.allLabels": "सभी लेबल",
"labels.changeColor": "रंग बदलें",
"labels.changeColorTooltip": "रंग बदलें",
"labels.clearAll": "सभी साफ करें",
"labels.confirmDelete": "क्या आप वाकई यह लेबल हटाना चाहते हैं?",
"labels.confirmDeleteShort": "पुष्टि करना?",
"labels.count": "{गिनती} लेबल",
"labels.createLabel": "लेबल बनाएं",
"labels.deleteTooltip": "लेबल हटाएँ",
"labels.editLabels": "लेबल संपादित करें",
"labels.editLabelsDescription": "रंग बनाएं, संपादित करें, या लेबल हटाएं।",
"labels.filter": "लेबल द्वारा फ़िल्टर करें",
"labels.filterByLabel": "लेबल द्वारा फ़िल्टर करें",
"labels.labelColor": "लेबल का रंग",
"labels.labelName": "लेबल का नाम",
"labels.labelRemoved": "लेबल \"{label}\" हटा दिया गया",
"labels.loading": "लोड हो रहा है...",
"labels.manage": "लेबल प्रबंधित करें",
"labels.manageTooltip": "लेबल प्रबंधित करें",
"labels.manageLabels": "लेबल प्रबंधित करें",
"labels.manageLabelsDescription": "इस नोट के लिए लेबल जोड़ें या हटाएँ. किसी लेबल का रंग बदलने के लिए उस पर क्लिक करें।",
"labels.namePlaceholder": "लेबल नाम दर्ज करें",
"labels.newLabelPlaceholder": "नया लेबल बनाएं",
"labels.noLabels": "कोई लेबल नहीं",
"labels.noLabelsFound": "कोई लेबल नहीं मिला.",
"labels.notebookRequired": "⚠️ लेबल केवल नोटबुक में उपलब्ध हैं। इस नोट को पहले एक नोटबुक में ले जाएँ।",
"labels.selectedLabels": "चयनित लेबल",
"labels.showLess": "कम दिखाओ",
"labels.showMore": "और दिखाएँ",
"labels.tagAdded": "टैग \"{tag}\" जोड़ा गया",
"labels.title": "लेबल",
"sidebar.labels": "लेबल",
"landing.pricing.perUser": "+3.90€/उपयोगकर्ता",
"landing.pricing.perUserAnnual": "+ 2.90€/उपयोगकर्ता, वार्षिक बिल",
"memoryEcho.fusion.generateError": "फ़्यूज़न उत्पन्न करने में विफल",
"memoryEcho.fusion.noContentReturned": "एपीआई से कोई फ़्यूज़न सामग्री वापस नहीं आई",
"memoryEcho.fusion.unknownDate": "अज्ञात तिथि",
"notebook.generatingDescription": "कृपया प्रतीक्षा करें...",
"notes.archiveFailed": "संग्रहित करने में विफल",
"notes.archived": "नोट संग्रहीत",
"notes.confirmDeleteTitle": "नोट हटाएँ",
"notes.content": "सामग्री",
"notes.conversionFailed": "मार्कडाउन में रहकर रूपांतरण विफल रहा",
"notes.convertedToRichText": "समृद्ध पाठ में कनवर्ट किया गया",
"notes.createFailed": "नोट बनाने में विफल",
"notes.deleteFailed": "नोट हटाने में विफल",
"notes.deleted": "नोट हटा दिया गया",
"notes.dismissed": "नोट हाल ही में खारिज कर दिया गया",
"notes.generalNotes": "सामान्य टिप्पणियां",
"notes.historyDisabledTitle": "संस्करण इतिहास",
"notes.historyEnabledDesc": "इस नोट के संस्करण अब रिकॉर्ड किए जाएंगे.",
"notes.historyEnabledTitle": "इतिहास सक्षम!",
"notes.leftShare": "शेयर हटा दिया गया",
"notes.restore": "पुनर्स्थापित करना",
"notes.sort": "क्रम से लगाना",
"notes.suggestTitle": "एआई शीर्षक",
"notes.titleGenerated": "शीर्षक उत्पन्न हुआ",
"notes.updateFailed": "नोट अद्यतन करने में विफल",
"notification.accept": "स्वीकार करना",
"notification.accepted": "शेयर स्वीकार किया गया",
"notification.decline": "गिरावट",
"notification.noNotifications": "कोई नए संदेश नहीं",
"profile.recentNotesUpdateFailed": "हालिया नोट्स सेटिंग अपडेट करने में विफल",
"profile.recentNotesUpdateSuccess": "हालिया नोट्स सेटिंग सफलतापूर्वक अपडेट की गई",
"profile.showRecentNotes": "हाल के नोट्स अनुभाग दिखाएँ",
"profile.showRecentNotesDescription": "मुख्य पृष्ठ पर हाल के नोट्स (पिछले 7 दिन) प्रदर्शित करें",
"profile.tab": "प्रोफ़ाइल",
"richTextEditor.imageUrlPlaceholder": "https://example.com/image.png",
"search.exactMatch": "बिल्कुल मेल",
"search.noResults": "कोई परिणाम नहीं मिला",
"search.placeholder": "खोज",
"usageMeter.featureSearch": "खोज",
"search.related": "संबंधित",
"search.resultsFound": "{गिनती} नोट मिले",
"search.searchPlaceholder": "अपने नोट्स खोजें...",
"search.searching": "खोज रहे हैं...",
"search.semanticInProgress": "एआई खोज प्रगति पर है...",
"search.semanticTooltip": "एआई सिमेंटिक खोज",
"settings.cardSizeMode": "नोट का आकार",
"settings.cardSizeModeDescription": "परिवर्तनीय आकार या समान आकार के बीच चयन करें",
"settings.cardSizeUniform": "वर्दी का आकार",
"settings.cardSizeVariable": "परिवर्तनीय आकार (छोटा/मध्यम/बड़ा)",
"settings.cleanTags": "स्वच्छ अनाथ टैग",
"settings.cleanTagsDescription": "उन टैग को हटा दें जिनका अब किसी भी नोट द्वारा उपयोग नहीं किया जाता है",
"settings.maintenanceDescription": "आपके डेटाबेस के स्वास्थ्य को बनाए रखने के लिए उपकरण",
"settings.selectCardSizeMode": "डिस्प्ले मोड चुनें",
"settings.semanticIndexing": "सिमेंटिक इंडेक्सिंग",
"settings.semanticIndexingDescription": "आशय-आधारित खोज को सक्षम करने के लिए सभी नोट्स के लिए वेक्टर उत्पन्न करें",
"settings.themeBaseGroup": "आधार",
"settings.themeBlue": "नीला",
"settings.themeGreen": "हरा",
"settings.themeLavender": "लैवेंडर",
"settings.themeMidnight": "मध्यरात्रि",
"settings.themeOcean": "महासागर",
"settings.themePalettesGroup": "रंग पट्टियाँ",
"settings.themeSand": "रेत",
"settings.themeSepia": "एक प्रकार की मछली",
"settings.themeSunset": "सूर्यास्त",
"sidebar.archive": "पुरालेख",
"sidebar.clearFilter": "फ़िल्टर हटाएँ",
"sidebar.editLabels": "लेबल संपादित करें",
"sidebar.reminders": "अनुस्मारक",
"sidebar.sharedNotebookBadge": "· साझा किया गया",
"sidebar.trash": "कचरा",
"usageMeter.addApiKey": "अपनी स्वयं की API कुंजी (BYOK) का उपयोग करें",
"usageMeter.featureBrainstormCreate": "मंथन रचनाएँ",
"usageMeter.featureBrainstormEnrich": "संवर्धन पर मंथन करें",
"usageMeter.featureBrainstormExpand": "विस्तार पर मंथन करें",
"usageMeter.featureChat": "एआई संदेश",
"usageMeter.featureReformulate": "सुधार",
"usageMeter.featureTags": "टैग",
"usageMeter.featureTitles": "टाइटल",
"usageMeter.later": "बाद में",
"usageMeter.packName": "एआई डिस्कवरी पैक",
"usageMeter.proChat": "100 चैट संदेश/माह",
"usageMeter.proIncludes": "प्रो में शामिल हैं:",
"usageMeter.proReformulate": "50 सुधार/माह",
"usageMeter.proSearch": "100 अर्थ संबंधी खोजें/माह",
"usageMeter.proTags": "200 ऑटो-टैग/माह",
"usageMeter.proTitles": "200 ऑटो-शीर्षक/माह",
"usageMeter.remaining": "{गिनती} बाएँ",
"usageMeter.unlimited": "असीमित",
"usageMeter.upgradeDescription": "आपने अपने सभी एआई डिस्कवरी पैक क्रेडिट का उपयोग कर लिया है। उच्च सीमा और अतिरिक्त सुविधाओं के लिए प्रो में अपग्रेड करें।",
"usageMeter.upgradePricing": "प्रो में अपग्रेड",
"usageMeter.upgradeTitle": "प्रो में अपग्रेड"
}

View File

@@ -0,0 +1,260 @@
{
"about.tab": "について",
"about.technology.ai": "AI",
"aiSettings.title": "AI",
"brainstorm.aiIdea": "AI",
"about.technology.ui": "UI",
"admin.ai.providerCustomOption": "🔧 カスタム OpenAI 互換",
"admin.ai.providerOllamaOption": "🦙 オラマ (ローカル&無料)",
"admin.email.activeAuto": "自動モード: 再送信が最初に使用され、SMTP がフォールバックとして使用されます。",
"admin.email.activeProvider": "アクティブなプロバイダー",
"admin.email.activeSmtp": "自動モード: SMTP が使用されます (再送信は構成されていません)。",
"admin.email.keySet": "設定されたキー",
"admin.email.noneConfigured": "電子メール サービスが設定されていません。再送信またはSMTPを設定します。",
"admin.email.status": "サービスステータス",
"admin.email.testFail": "テストは失敗しました",
"admin.email.testOk": "テストに合格しました",
"admin.tools.brave": "Brave検索API",
"admin.tools.searxngUrl": "SeaXNG URL",
"admin.users.table.subscription": "サブスクリプション",
"admin.users.tierUpdateFailed": "サブスクリプションの更新に失敗しました",
"admin.users.tierUpdateSuccess": "サブスクリプションが {tier} に更新されました",
"agents.filterAll": "全て",
"agents.form.back": "戻る",
"agents.form.includeImages": "画像を含める",
"agents.form.includeImagesHint": "スクレイピングしたページから画像を抽出し、生成されたメモに添付します",
"agents.help.advancedContent": "追加の設定にアクセスするには、フォームの下部にある **「詳細モード」** をクリックします。\n\n### AI の指示\n\nこのフィールドを使用すると、エージェントの**デフォルトのシステム プロンプト**を置き換えることができます。空のままにすると、エージェントはそのタイプに応じた自動プロンプトを使用します。\n\n**これを使用する理由** エージェントの動作を正確に制御したいと考えています。たとえば:\n- 「たとえソースがフランス語であっても、概要は英語で書きます」\n- 「メモをセクションで構成する: コンテキスト、キーポイント、個人的な意見」\n- 「30 日より古い記事は無視し、最近のニュースに焦点を当てます」\n- 「検出されたテーマごとに、リンクを含む 3 つのフォローアップ見込み客を提案します」\n\n> **注意:** 指示はデフォルトを置き換えるものであり、追加するものではありません。\n\n### 最大反復回数\n\nこれは、エージェントが実行できる**最大サイクル数**です。 1 サイクル = エージェントが考え、ツールを呼び出し、結果を読み取り、次のアクションを決定します。\n\n- **3 5 回の反復:** 単純なタスク (単一ページのスクレイピング)\n- **10 回の反復 (デフォルト):** ほとんどの場合に良好なバランス\n- **15 25 回の反復:** エージェントが複数のリードを探索する必要がある詳細な調査の場合\n\n> **警告:** 反復回数が増えると、時間がかかり、API コストが高くなる可能性があります。",
"agents.help.frequencyContent": "|周波数 |行動\n|----------|----------\n| **マニュアル** |自分で「実行」をクリックします - 自動スケジュールはありません\n| **毎時** | Runs every hour\n| **毎日** | 1 日に 1 回実行されます\n| **毎週** |週に 1 回実行\n| **毎月** |月に 1 回実行\n\n> **ヒント:** まず「手動」でエージェントをテストし、結果に満足できたら自動頻度に切り替えます。",
"agents.help.howToUseContent": "1. **「新しいエージェント」** をクリックします (または、ページの下部にある **テンプレート** から開始します)\n2. **エージェント タイプ** (リサーチャー、モニター、オブザーバー、カスタム) を選択します。\n3. **名前**を付け、タイプ固有のフィールドに入力します\n4. 必要に応じて、結果が保存される **ターゲット ノートブック** を選択します\n5. **周波数**を選択します (手動 = 自分でトリガーします)\n6. [**作成**] をクリックし、エージェント カードの [**実行**] ボタンを押します。\n7. 完了すると、ターゲットノートブックに新しいノートが表示されます。",
"agents.help.targetNotebookContent": "エージェントはタスクを完了すると、**メモを作成**します。 **ターゲット ノートブック** によって、そのメモの保存場所が決まります。\n\n- **受信箱** (デフォルト) — メモは一般的なメモに移動します\n- **特定のノートブック** — エージェントの結果を整理しておくためにノートブックを選択します\n\n> **ヒント:** 「エージェント レポート」のような専用のノートブックを作成して、すべての自動コンテンツを 1 か所に保管します。",
"agents.newBadge": "新しい",
"agents.noResults": "検索に一致するエージェントはありません。",
"agents.schedule.dayOfMonth": "月の日",
"agents.schedule.dayOfWeek": "曜日",
"agents.schedule.days.fri": "金曜日",
"agents.schedule.days.mon": "月曜日",
"agents.schedule.days.sat": "土曜日",
"agents.schedule.days.sun": "日曜日",
"agents.schedule.days.thu": "木曜日",
"agents.schedule.days.tue": "火曜日",
"agents.schedule.days.wed": "水曜日",
"agents.schedule.nextRun": "次の実行",
"agents.schedule.pending": "保留中のトリガー",
"agents.schedule.time": "時間",
"agents.searchPlaceholder": "エージェントを検索...",
"agents.toasts.autoRunError": "エージェント「{name}」が自動実行中に失敗しました",
"agents.toasts.autoRunSuccess": "エージェント「{name}」は自動的に実行され、成功しました",
"ai.action.describeImages": "画像の説明",
"ai.contextSourceHeading": "コンテキストソース",
"ai.featureLocked": "この機能を利用するには、PRO プラン以上が必要です。",
"ai.generateTitleFromImage": "画像からタイトルを生成",
"notes.generateTitleFromImage": "画像からタイトルを生成",
"ai.noImagesError": "このノートには画像がありません",
"ai.overview": "概要",
"ai.quotaExceeded": "月間制限に達しました。来月リセット。",
"ai.titleGenerated": "画像から生成されたタイトル",
"ai.tones.academic": "アカデミック",
"ai.tones.casual": "カジュアル",
"ai.tones.creative": "クリエイティブ",
"ai.tones.professional": "プロ",
"appearance.fontInterDefault": "インター (デフォルト)",
"appearance.selectTheme": "テーマの選択",
"appearance.tab": "外観",
"billing.businessAnnualPrice": "299ユーロ",
"billing.businessPrice": "€29.90",
"billing.enterpriseTitle": "企業",
"billing.proAnnualPrice": "99ユーロ",
"billing.proPrice": "€9.90",
"billing.tab": "請求する",
"brainstorm.addIdea": "アイデアを追加する",
"brainstorm.brainstormThisIdea": "このアイデアについてブレインストーミングを行う",
"brainstorm.cancel": "キャンセル",
"brainstorm.canvasChildBranch": "子供",
"brainstorm.canvasDoubleClickHint": "ダブルクリックしてアイデアを追加します",
"brainstorm.canvasEditTitleNewIdea": "新しいアイデア",
"brainstorm.canvasEditTitleReply": "返事",
"brainstorm.canvasPlaceholderIdea": "あなたのアイデアは…",
"brainstorm.canvasPlaceholderReply": "あなたの返事は…",
"brainstorm.canvasShortcutCancel": "キャンセル",
"brainstorm.canvasShortcutSave": "保存",
"brainstorm.canvasWaitingHint": "キャンバスはあなたの輝きを待っています...",
"brainstorm.convertedToNoteStatus": "ノートに変換しました",
"brainstorm.converting": "変換中...",
"brainstorm.deepen": "深める",
"brainstorm.deepening": "生成中...",
"brainstorm.delete": "消去",
"brainstorm.derived_from": "由来",
"brainstorm.dismiss": "関係ありません",
"notes.dismiss": "関係ありません",
"brainstorm.export": "輸出",
"brainstorm.exportDefaultNoteTitle": "合成",
"brainstorm.exportFailedMessage": "エクスポートに失敗しました",
"brainstorm.exportNotebookPrefix": "ノート:",
"brainstorm.exportOpening": "オープニング…",
"brainstorm.exporting": "エクスポート中...",
"brainstorm.extends": "伸びる",
"brainstorm.extract": "メモの作成",
"brainstorm.feedbackAlreadyPending": "この人の招待はすでに保留中です。",
"brainstorm.feedbackAlreadyShared": "この人はすでにこのブレインストーミングにアクセスできます。",
"brainstorm.feedbackGenericError": "エラー",
"brainstorm.feedbackInviteResent": "招待状を再送信しました!",
"brainstorm.feedbackInviteSent": "招待状を送信しました!",
"brainstorm.generating": "AI は思考の種を収穫しています...",
"brainstorm.guestReadOnlyNotice": "あなたはこのブレインストーミングをゲストとして視聴しています。編集するにはサインインしてください。",
"brainstorm.ideaDetailConnection": "繋がり",
"brainstorm.ideaDetailNovelty": "ノベルティ",
"brainstorm.novelty": "ノベルティ",
"brainstorm.ideaDetailWave": "波",
"brainstorm.wave": "波",
"brainstorm.ideaOrigin": "アイデアの原点",
"notes.ideaOrigin": "アイデアの原点",
"brainstorm.ideas": "アイデア",
"brainstorm.impactNotesEnriched": "{count} 個のノートが強化されました",
"brainstorm.impactNotesMarkedDry": "{count} 個のノートがドライとマークされました",
"brainstorm.invite": "招待する",
"brainstorm.legendDisruptions": "混乱",
"brainstorm.legendSeed": "シード",
"brainstorm.linkCopied": "招待リンクがコピーされました!",
"brainstorm.linkedNotes": "リンクされたメモ",
"brainstorm.liveCollaborationTitle": "ライブコラボレーション",
"brainstorm.liveOtherParticipants": "他に {count} 人の参加者",
"brainstorm.liveStatus": "ライブ",
"brainstorm.liveYouMarker": "(あなた)",
"brainstorm.manualIdeaPrompt": "あなたのアイデアのタイトル:",
"brainstorm.newBrainstorm": "新しいブレインストーミング",
"brainstorm.noNoteLink": "純粋に生成的なアイデア",
"notes.noNoteLink": "純粋に生成的なアイデア",
"brainstorm.noSessions": "まだブレインストーミングはありません",
"brainstorm.none_found": "メモのリンクがありません",
"brainstorm.noteCreated": "メモが作成されました",
"brainstorm.opposes": "と反対して",
"brainstorm.originConnection": "オリジン接続",
"brainstorm.originalSeedDescription": "オリジナルのシードアイデア",
"brainstorm.ownerBadge": "所有者",
"brainstorm.placeholder": "展開するコンセプトを入力してください...",
"brainstorm.playbackReturnToLive": "ライブに戻る",
"brainstorm.playbackStep": "ステップ {現在}/{合計}",
"brainstorm.playbackStepsCount": "{count} 歩",
"brainstorm.seedLabel": "シードアイデア",
"brainstorm.seedNodeBadge": "シード",
"brainstorm.sessions": "ブレインストーミング",
"brainstorm.shareDialogTitle": "ブレインストーミングを共有する",
"brainstorm.shareFooterHint": "承認または拒否するための通知が届きます。",
"brainstorm.shareGuestsCanEdit": "ゲストに編集を許可する",
"brainstorm.shareNameOrEmailPlaceholder": "名前またはメールアドレス…",
"brainstorm.sharePublicLink": "パブリックリンク",
"brainstorm.shareSearchLabel": "誰かを探す",
"brainstorm.shareSubmit": "共有",
"brainstorm.shareSubmitting": "送信中…",
"brainstorm.spatialMode": "空間探索モード",
"brainstorm.startBrainstorm": "ブレーンストーミングを開始する",
"brainstorm.startOne": "一つ始めてください",
"brainstorm.subtitle": "可能性の次元を広げる",
"brainstorm.synthesizes": "合成する",
"brainstorm.title": "思考の波",
"brainstorm.toastConvertFailed": "変換に失敗しました",
"brainstorm.toastConvertSuccess": "アイデアをnoteに変換",
"brainstorm.toastDismissFailed": "却下できませんでした",
"brainstorm.toastDismissSuccess": "アイデアは却下されました",
"brainstorm.toastExpandFailed": "展開に失敗しました",
"brainstorm.toastExpandSuccess": "アイデアが広がりました!",
"brainstorm.toastExportFailed": "エクスポートに失敗しました",
"brainstorm.toastExportNoteSuccess": "メモとしてエクスポートされました!",
"brainstorm.transposes": "移調",
"brainstorm.unnamedPerson": "名前なし",
"brainstorm.viewNote": "メモを見る",
"brainstorm.wave1": "ウェーブ 1",
"brainstorm.wave2": "ウェーブ 2",
"brainstorm.wave3": "ウェーブ 3",
"brainstorm.waveBadge": "波 {波}",
"brainstorm.waveFlavorAnalogy": "類推",
"byokSettings.alias": "ラベル (オプション)",
"byokSettings.aliasPlaceholder": "例えば作品 OpenAI",
"byokSettings.apiKey": "APIキー",
"byokSettings.badgeActive": "BYOK アクティブ",
"byokSettings.confirmDelete": "この API キーを完全に削除しますか?",
"byokSettings.deleted": "APIキーが削除されました",
"byokSettings.description": "独自の LLM プロバイダー キーを接続して、Discovery Pack クォータをバイパスします。キーは保存時に暗号化されます。",
"byokSettings.empty": "API キーがまだ設定されていません。",
"byokSettings.error": "APIキーを保存できませんでした",
"byokSettings.loadError": "API キーをロードできませんでした",
"byokSettings.loading": "キーをロード中...",
"byokSettings.provider": "プロバイダー",
"byokSettings.providerPlaceholder": "プロバイダーを選択してください",
"byokSettings.save": "キーを保存",
"byokSettings.saved": "APIキーが保存されました",
"byokSettings.tierRequired": "BYOK には Pro プラン以上が必要です。 API キーを接続するにはアップグレードしてください。",
"byokSettings.title": "API キー (BYOK)",
"chat.timeoutWarning": "返答に予想以上に時間がかかっています...",
"dataManagement.title": "データ",
"generalSettings.title": "一般的な",
"labHeader.rename": "名前の変更",
"landing.pricing.perUser": "+ 3.90ユーロ/ユーザー",
"landing.pricing.perUserAnnual": "+ 2.90 ユーロ/ユーザー、毎年請求",
"notebook.generatingDescription": "お待ちください...",
"notes.archiveFailed": "アーカイブに失敗しました",
"notes.archived": "メモがアーカイブされました",
"notes.confirmDeleteTitle": "メモを削除する",
"notes.content": "コンテンツ",
"notes.conversionFailed": "変換に失敗し、Markdown のままになります",
"notes.convertedToRichText": "リッチテキストに変換",
"notes.createFailed": "メモの作成に失敗しました",
"notes.deleteFailed": "メモの削除に失敗しました",
"notes.deleted": "メモが削除されました",
"notes.dismissed": "最近のメモから却下されました",
"notes.generalNotes": "一般的な注意事項",
"notes.historyDisabledTitle": "バージョン履歴",
"notes.historyEnabledDesc": "このメモのバージョンが記録されます。",
"notes.historyEnabledTitle": "履歴が有効になりました!",
"notes.leftShare": "共有が削除されました",
"notes.restore": "復元する",
"notes.sort": "選別",
"notes.suggestTitle": "AIタイトル",
"notes.titleGenerated": "タイトル生成",
"notes.updateFailed": "メモの更新に失敗しました",
"notification.accept": "受け入れる",
"notification.accepted": "シェアが承認されました",
"notification.decline": "衰退",
"notification.noNotifications": "新しい通知はありません",
"profile.tab": "プロフィール",
"richTextEditor.imageUrlPlaceholder": "https://example.com/image.png",
"settings.cardSizeMode": "ノートのサイズ",
"settings.cardSizeModeDescription": "可変サイズまたは均一サイズのどちらかを選択してください",
"settings.cardSizeUniform": "均一なサイズ",
"settings.cardSizeVariable": "可変サイズ(小/中/大)",
"settings.selectCardSizeMode": "表示モードの選択",
"settings.themeBaseGroup": "ベース",
"settings.themeBlue": "青",
"settings.themeGreen": "緑",
"settings.themeLavender": "ラベンダー",
"settings.themeMidnight": "夜中",
"settings.themeOcean": "海",
"settings.themePalettesGroup": "カラーパレット",
"settings.themeSand": "砂",
"settings.themeSepia": "セピア",
"settings.themeSunset": "日没",
"sidebar.clearFilter": "フィルターを削除する",
"sidebar.sharedNotebookBadge": "· 共有",
"usageMeter.addApiKey": "独自の API キーを使用する (BYOK)",
"usageMeter.featureBrainstormCreate": "作品のブレインストーミング",
"usageMeter.featureBrainstormEnrich": "ブレーンストーミングの強化",
"usageMeter.featureBrainstormExpand": "拡張のブレインストーミング",
"usageMeter.featureChat": "AIメッセージ",
"usageMeter.featureReformulate": "再定式化",
"usageMeter.featureSearch": "検索",
"usageMeter.featureTags": "タグ",
"usageMeter.featureTitles": "タイトル",
"usageMeter.later": "後で",
"usageMeter.packName": "AI ディスカバリー パック",
"usageMeter.proChat": "100 チャット メッセージ/月",
"usageMeter.proIncludes": "プロには次のものが含まれます。",
"usageMeter.proReformulate": "50回の再配合/月",
"usageMeter.proSearch": "100 件のセマンティック検索/月",
"usageMeter.proTags": "200 自動タグ/月",
"usageMeter.proTitles": "200 オートタイトル / 月",
"usageMeter.remaining": "残り {count} 個",
"usageMeter.unlimited": "無制限",
"usageMeter.upgradeDescription": "AI Discovery Pack のクレジットをすべて使用しました。 Pro にアップグレードすると、より高い制限と追加機能が利用できます。",
"usageMeter.upgradePricing": "プロにアップグレード",
"usageMeter.upgradeTitle": "プロにアップグレード"
}

View File

@@ -0,0 +1,281 @@
{
"about.tab": "에 대한",
"about.technology.ai": "AI",
"aiSettings.title": "일체 포함",
"about.technology.ui": "UI",
"admin.email.activeAuto": "자동 모드: 재전송이 먼저 사용되고 SMTP가 대체 수단으로 사용됩니다.",
"admin.email.activeProvider": "활성 공급자",
"admin.email.activeSmtp": "자동 모드: SMTP가 사용됩니다(재전송이 구성되지 않음).",
"admin.email.keySet": "키 구성",
"admin.email.noneConfigured": "이메일 서비스가 구성되지 않았습니다. 재전송 또는 SMTP를 설정하세요.",
"admin.email.status": "서비스 현황",
"admin.email.testFail": "테스트 실패",
"admin.email.testOk": "테스트 통과",
"admin.tools.brave": "용감한 검색 API",
"admin.tools.searxngUrl": "SearXNG URL",
"admin.users.table.subscription": "신청",
"admin.users.tierUpdateFailed": "구독을 업데이트하지 못했습니다.",
"admin.users.tierUpdateSuccess": "구독이 {tier}로 업데이트되었습니다.",
"agents.filterAll": "모두",
"agents.form.back": "뒤쪽에",
"agents.form.includeImages": "이미지 포함",
"agents.form.includeImagesHint": "스크랩한 페이지에서 이미지를 추출하여 생성된 노트에 첨부합니다.",
"agents.help.advancedContent": "추가 설정에 액세스하려면 양식 하단의 **\"고급 모드\"**를 클릭하세요.\n\n### AI 지침\n\n이 필드를 사용하면 상담원의 **기본 시스템 프롬프트를 대체**할 수 있습니다. 비워 두면 에이전트는 해당 유형에 맞는 자동 프롬프트를 사용합니다.\n\n**이를 사용하는 이유는 무엇입니까?** 에이전트의 작동 방식을 정확하게 제어하고 싶습니다. 예를 들면:\n- \"출처가 프랑스어인 경우에도 요약을 영어로 작성하세요\"\n- \"컨텍스트, 핵심 포인트, 개인 의견 등 섹션으로 메모를 구성하세요.\"\n- \"30일이 지난 기사는 무시하고 최근 뉴스에만 집중하세요\"\n- \"감지된 각 테마에 대해 링크가 포함된 후속 리드 3개 제안\"\n\n> **참고:** 귀하의 지침은 기본값을 대체하지만 기본값에 추가되지는 않습니다.\n\n### 최대 반복\n\n이는 에이전트가 수행할 수 있는 **최대 주기 수**입니다. 한 주기 = 에이전트가 생각하고 도구를 호출하고 결과를 읽은 후 다음 작업을 결정합니다.\n\n- **3~5회 반복:** 간단한 작업의 경우(단일 페이지 스크랩)\n- **10회 반복(기본값):** 대부분의 경우 좋은 균형\n- **15~25회 반복:** 상담사가 여러 리드를 탐색해야 하는 심층 연구의 경우\n\n> **경고:** 반복 횟수 증가 = 시간이 더 걸리고 API 비용이 더 높아질 수 있습니다.",
"agents.help.frequencyContent": "| 빈도 | 행동\n|------------|----------\n| **수동** | 직접 \"실행\"을 클릭하면 자동 예약 기능이 없습니다.\n| **시간별** | 매 시간마다 실행\n| **매일** | 하루에 한 번 실행됩니다.\n| **주간** | 주 1회 운행\n| **월간** | 한 달에 한 번 실행됩니다.\n\n> **팁:** 에이전트를 테스트하려면 \"수동\"으로 시작한 다음 결과에 만족하면 자동 빈도로 전환하세요.",
"agents.help.howToUseContent": "1. **\"새 에이전트\"**를 클릭합니다(또는 페이지 하단의 **템플릿**에서 시작).\n2. **에이전트 유형**(연구원, 모니터, 관찰자, 사용자 지정)을 선택합니다.\n3. **이름**을 지정하고 유형별 필드를 입력합니다.\n4. 선택적으로 결과가 저장될 **대상 노트북**을 선택합니다.\n5. **빈도**를 선택합니다(수동 = 사용자가 직접 트리거).\n6. **만들기**를 클릭한 다음 에이전트 카드에서 **실행** 버튼을 누릅니다.\n7. 완료되면 대상 노트북에 새 노트가 나타납니다.",
"agents.help.targetNotebookContent": "상담원이 작업을 마치면 **메모를 작성**합니다. **대상 노트북**은 해당 노트의 위치를 결정합니다.\n\n- **받은 편지함**(기본값) — 메모가 일반 메모로 이동됩니다.\n- **특정 노트북** - 상담원 결과를 체계적으로 정리할 노트북을 선택하세요.\n\n> **팁:** 모든 자동화된 콘텐츠를 한 곳에 보관하려면 \"에이전트 보고서\"와 같은 전용 노트북을 만드세요.",
"agents.newBadge": "새로운",
"agents.noResults": "검색어와 일치하는 상담원이 없습니다.",
"agents.schedule.dayOfMonth": "해당 월의 일",
"agents.schedule.dayOfWeek": "요일",
"agents.schedule.days.fri": "금요일",
"agents.schedule.days.mon": "월요일",
"agents.schedule.days.sat": "토요일",
"agents.schedule.days.sun": "일요일",
"agents.schedule.days.thu": "목요일",
"agents.schedule.days.tue": "화요일",
"agents.schedule.days.wed": "수요일",
"agents.schedule.nextRun": "다음 실행",
"agents.schedule.pending": "보류 중인 트리거",
"agents.schedule.time": "시간",
"agents.searchPlaceholder": "검색 에이전트...",
"agents.toasts.autoRunError": "자동 실행 중 \"{name}\" 에이전트가 실패했습니다.",
"agents.toasts.autoRunSuccess": "\"{name}\" 에이전트가 자동으로 성공적으로 실행되었습니다.",
"ai.action.describeImages": "이미지 설명",
"ai.contextSourceHeading": "컨텍스트 소스",
"ai.featureLocked": "이 기능을 사용하려면 PRO 플랜 이상이 필요합니다.",
"ai.generateTitleFromImage": "이미지에서 제목 생성",
"notes.generateTitleFromImage": "이미지에서 제목 생성",
"ai.noImagesError": "이 메모에는 이미지가 없습니다.",
"ai.overview": "개요",
"ai.quotaExceeded": "월별 한도에 도달했습니다. 다음달에 초기화됩니다.",
"ai.titleGenerated": "이미지에서 생성된 제목",
"ai.tones.academic": "학생",
"ai.tones.casual": "평상복",
"ai.tones.creative": "창의적인",
"ai.tones.professional": "전문적인",
"appearance.fontInterDefault": "인터(기본값)",
"appearance.selectTheme": "테마 선택",
"appearance.tab": "모습",
"billing.businessAnnualPrice": "€299",
"billing.businessPrice": "€29.90",
"billing.enterpriseTitle": "기업",
"billing.proAnnualPrice": "€99",
"billing.proPrice": "€9.90",
"billing.tab": "청구",
"brainstorm.addIdea": "아이디어 추가",
"brainstorm.brainstormThisIdea": "이 아이디어를 브레인스토밍하세요",
"brainstorm.cancel": "취소",
"brainstorm.canvasChildBranch": "어린이",
"brainstorm.canvasDoubleClickHint": "아이디어를 추가하려면 두 번 클릭하세요.",
"brainstorm.canvasEditTitleNewIdea": "신안",
"brainstorm.canvasEditTitleReply": "회신하다",
"brainstorm.canvasPlaceholderIdea": "당신의 아이디어…",
"brainstorm.canvasPlaceholderReply": "귀하의 답변은…",
"brainstorm.canvasShortcutCancel": "취소",
"brainstorm.canvasShortcutSave": "구하다",
"brainstorm.canvasWaitingHint": "캔버스가 당신의 불꽃을 기다리고 있습니다...",
"brainstorm.convertedToNoteStatus": "메모로 변환됨",
"brainstorm.converting": "변환 중...",
"brainstorm.deepen": "깊게 하다",
"brainstorm.deepening": "생성 중...",
"brainstorm.delete": "삭제",
"labels.delete": "삭제",
"brainstorm.derived_from": "파생됨",
"brainstorm.dismiss": "관련 없음",
"notes.dismiss": "관련 없음",
"brainstorm.export": "내보내다",
"brainstorm.exportDefaultNoteTitle": "합성",
"brainstorm.exportFailedMessage": "내보내기 실패",
"brainstorm.exportNotebookPrefix": "공책:",
"brainstorm.exportOpening": "열기…",
"brainstorm.exporting": "내보내는 중...",
"brainstorm.extends": "확장",
"brainstorm.extract": "메모 작성",
"brainstorm.feedbackAlreadyPending": "이 사람에 대한 초대가 이미 대기 중입니다.",
"brainstorm.feedbackAlreadyShared": "이 사람은 이미 이 브레인스토밍에 액세스할 수 있습니다.",
"brainstorm.feedbackGenericError": "오류",
"brainstorm.feedbackInviteResent": "초대를 다시 보냈습니다.",
"brainstorm.feedbackInviteSent": "초대장이 전송되었습니다!",
"brainstorm.generating": "AI는 생각의 씨앗을 수확하고 있다.",
"brainstorm.guestReadOnlyNotice": "귀하는 손님으로서 이 브레인스토밍을 보고 계십니다. 편집하려면 로그인하세요.",
"brainstorm.ideaDetailConnection": "연결",
"brainstorm.ideaDetailNovelty": "진기함",
"brainstorm.novelty": "진기함",
"brainstorm.ideaDetailWave": "파도",
"brainstorm.wave": "파도",
"brainstorm.ideaOrigin": "아이디어의 유래",
"notes.ideaOrigin": "아이디어의 유래",
"brainstorm.ideas": "아이디어",
"brainstorm.impactNotesEnriched": "{count}개의 메모가 강화되었습니다.",
"brainstorm.impactNotesMarkedDry": "건조한 것으로 표시된 메모 {count}개",
"brainstorm.invite": "초대하다",
"brainstorm.legendDisruptions": "중단",
"brainstorm.legendSeed": "씨앗",
"brainstorm.linkCopied": "초대 링크가 복사되었습니다!",
"brainstorm.linkedNotes": "연결된 노트",
"brainstorm.liveCollaborationTitle": "실시간 협업",
"brainstorm.liveOtherParticipants": "{count}명의 다른 참가자",
"brainstorm.liveStatus": "살다",
"brainstorm.liveYouMarker": "(너)",
"brainstorm.manualIdeaPrompt": "아이디어 제목:",
"brainstorm.newBrainstorm": "새로운 브레인스토밍",
"brainstorm.noNoteLink": "순전히 생성적인 아이디어",
"notes.noNoteLink": "순전히 생성적인 아이디어",
"brainstorm.noSessions": "아직 브레인스토밍이 없습니다.",
"brainstorm.none_found": "메모 링크 없음",
"brainstorm.noteCreated": "메모가 생성되었습니다.",
"brainstorm.opposes": "반대하다",
"brainstorm.originConnection": "원점 연결",
"brainstorm.originalSeedDescription": "독창적인 종자 아이디어",
"brainstorm.ownerBadge": "소유자",
"brainstorm.placeholder": "전개할 개념을 입력하세요...",
"brainstorm.playbackReturnToLive": "라이브로 돌아가기",
"brainstorm.playbackStep": "단계 {현재}/{총계}",
"brainstorm.playbackStepsCount": "{count}걸음",
"brainstorm.seedLabel": "씨앗 아이디어",
"brainstorm.seedNodeBadge": "씨앗",
"brainstorm.sessions": "브레인스토밍",
"brainstorm.shareDialogTitle": "브레인스토밍 공유",
"brainstorm.shareFooterHint": "수락하거나 거부하라는 알림을 받게 됩니다.",
"brainstorm.shareGuestsCanEdit": "손님이 편집하도록 허용",
"brainstorm.shareNameOrEmailPlaceholder": "이름이나 이메일…",
"brainstorm.sharePublicLink": "공개 링크",
"brainstorm.shareSearchLabel": "누군가를 찾아보세요",
"brainstorm.shareSubmit": "공유하다",
"brainstorm.shareSubmitting": "배상…",
"brainstorm.spatialMode": "공간 탐색 모드",
"brainstorm.startBrainstorm": "브레인스토밍 시작",
"brainstorm.startOne": "하나 시작하세요",
"brainstorm.subtitle": "잠재력의 차원을 펼쳐보세요",
"brainstorm.synthesizes": "합성하다",
"brainstorm.title": "생각의 파도",
"brainstorm.toastConvertFailed": "변환 실패",
"brainstorm.toastConvertSuccess": "아이디어가 노트로 전환되었습니다!",
"brainstorm.toastDismissFailed": "닫을 수 없습니다.",
"brainstorm.toastDismissSuccess": "아이디어가 기각되었습니다.",
"brainstorm.toastExpandFailed": "확장하지 못했습니다.",
"brainstorm.toastExpandSuccess": "아이디어가 확장되었습니다!",
"brainstorm.toastExportFailed": "내보내지 못했습니다.",
"brainstorm.toastExportNoteSuccess": "메모로 내보냈습니다!",
"brainstorm.transposes": "조옮김",
"brainstorm.unnamedPerson": "이름 없음",
"brainstorm.viewNote": "메모 보기",
"brainstorm.wave1": "웨이브 1",
"brainstorm.wave2": "웨이브 2",
"brainstorm.wave3": "웨이브 3",
"brainstorm.waveBadge": "웨이브 {파}",
"brainstorm.waveFlavorAnalogy": "유추",
"byokSettings.alias": "라벨(선택사항)",
"byokSettings.aliasPlaceholder": "예를 들어 OpenAI 작업",
"byokSettings.apiKey": "API 키",
"byokSettings.badgeActive": "BYOK 활성",
"byokSettings.confirmDelete": "이 API 키를 영구적으로 삭제하시겠습니까?",
"byokSettings.deleted": "API 키가 삭제됨",
"byokSettings.description": "자체 LLM 공급자 키를 연결하여 Discovery Pack 할당량을 우회하세요. 키는 저장 시 암호화됩니다.",
"byokSettings.empty": "아직 구성된 API 키가 없습니다.",
"byokSettings.error": "API 키를 저장할 수 없습니다.",
"byokSettings.loadError": "API 키를 로드할 수 없습니다.",
"byokSettings.loading": "키 로드 중...",
"byokSettings.provider": "공급자",
"byokSettings.providerPlaceholder": "제공업체 선택",
"byokSettings.save": "키 저장",
"byokSettings.saved": "API 키가 저장되었습니다",
"byokSettings.tierRequired": "BYOK에는 Pro 플랜 이상이 필요합니다. API 키를 연결하려면 업그레이드하세요.",
"byokSettings.title": "API 키(BYOK)",
"chat.timeoutWarning": "응답이 예상보다 오래 걸리고 있습니다.",
"dataManagement.title": "데이터",
"generalSettings.title": "일반적인",
"labHeader.rename": "이름 바꾸기",
"labels.createLabel": "라벨 만들기",
"labels.deleteTooltip": "라벨 삭제",
"labels.editLabels": "라벨 편집",
"labels.editLabelsDescription": "색상을 생성, 편집하거나 라벨을 삭제합니다.",
"labels.filter": "라벨로 필터링",
"labels.filterByLabel": "라벨로 필터링",
"labels.labelColor": "라벨 색상",
"labels.labelName": "라벨 이름",
"labels.loading": "로드 중...",
"labels.manage": "라벨 관리",
"labels.manageTooltip": "라벨 관리",
"labels.manageLabels": "라벨 관리",
"labels.manageLabelsDescription": "이 메모에 라벨을 추가하거나 삭제하세요. 색상을 변경하려면 라벨을 클릭하세요.",
"labels.namePlaceholder": "라벨 이름을 입력하세요.",
"labels.newLabelPlaceholder": "새 라벨 만들기",
"labels.noLabelsFound": "라벨을 찾을 수 없습니다.",
"labels.notebookRequired": "⚠️ 라벨은 노트에서만 사용 가능합니다. 먼저 이 노트를 노트북으로 이동하세요.",
"labels.selectedLabels": "선택한 라벨",
"labels.showLess": "간략히 보기",
"labels.showMore": "더 보기",
"labels.tagAdded": "\"{tag}\" 태그가 추가되었습니다",
"labels.title": "라벨",
"landing.pricing.perUser": "+ 3.90€/사용자",
"landing.pricing.perUserAnnual": "+ 2.90€/사용자, 연간 청구",
"notebook.generatingDescription": "기다리세요...",
"notes.archiveFailed": "보관하지 못했습니다.",
"notes.archived": "메모가 보관되었습니다.",
"notes.confirmDeleteTitle": "메모 삭제",
"notes.content": "콘텐츠",
"notes.conversionFailed": "변환 실패, Markdown 유지",
"notes.convertedToRichText": "서식 있는 텍스트로 변환됨",
"notes.createFailed": "메모를 작성하지 못했습니다.",
"notes.deleteFailed": "메모를 삭제하지 못했습니다.",
"notes.deleted": "메모가 삭제되었습니다.",
"notes.dismissed": "최근 메모가 닫혔습니다.",
"notes.generalNotes": "일반 사항",
"notes.historyDisabledTitle": "버전 기록",
"notes.historyEnabledDesc": "이제 이 메모의 버전이 기록됩니다.",
"notes.historyEnabledTitle": "기록이 활성화되었습니다!",
"notes.leftShare": "공유가 삭제되었습니다.",
"notes.restore": "복원하다",
"notes.sort": "종류",
"notes.suggestTitle": "AI 제목",
"notes.titleGenerated": "제목이 생성되었습니다.",
"notes.updateFailed": "메모를 업데이트하지 못했습니다.",
"notification.accept": "수용하다",
"notification.accepted": "공유 승인됨",
"notification.decline": "감소",
"notification.noNotifications": "새로운 알림 없음",
"profile.tab": "윤곽",
"richTextEditor.imageUrlPlaceholder": "https://example.com/image.png",
"settings.cardSizeMode": "노트 크기",
"settings.cardSizeModeDescription": "다양한 크기 또는 균일한 크기 중에서 선택하세요.",
"settings.cardSizeUniform": "균일한 크기",
"settings.cardSizeVariable": "다양한 크기(소/중/대)",
"settings.selectCardSizeMode": "디스플레이 모드 선택",
"settings.themeBaseGroup": "베이스",
"settings.themeBlue": "파란색",
"settings.themeGreen": "녹색",
"settings.themeLavender": "라벤더",
"settings.themeMidnight": "자정",
"settings.themeOcean": "대양",
"settings.themePalettesGroup": "색상 팔레트",
"settings.themeSand": "모래",
"settings.themeSepia": "세피아",
"settings.themeSunset": "일몰",
"sidebar.clearFilter": "필터 제거",
"sidebar.sharedNotebookBadge": "· 공유",
"sidebar.sortAlpha": "A → Z",
"usageMeter.addApiKey": "자체 API 키 사용(BYOK)",
"usageMeter.featureBrainstormCreate": "브레인스토밍 창작물",
"usageMeter.featureBrainstormEnrich": "브레인스토밍 강화",
"usageMeter.featureBrainstormExpand": "브레인스토밍 확장",
"usageMeter.featureChat": "AI 메시지",
"usageMeter.featureReformulate": "재구성",
"usageMeter.featureSearch": "찾다",
"usageMeter.featureTags": "태그",
"usageMeter.featureTitles": "제목",
"usageMeter.later": "나중에",
"usageMeter.packName": "AI 디스커버리 팩",
"usageMeter.proChat": "채팅 메시지 100개/월",
"usageMeter.proIncludes": "프로에는 다음이 포함됩니다:",
"usageMeter.proReformulate": "50개 재구성/월",
"usageMeter.proSearch": "의미 검색 100개/월",
"usageMeter.proTags": "자동 태그 200개/월",
"usageMeter.proTitles": "자동 타이틀 200개/월",
"usageMeter.remaining": "{count} 남음",
"usageMeter.unlimited": "제한 없는",
"usageMeter.upgradeDescription": "AI Discovery Pack 크레딧을 모두 사용했습니다. 더 높은 한도와 추가 기능을 이용하려면 Pro로 업그레이드하세요.",
"usageMeter.upgradePricing": "프로로 업그레이드",
"usageMeter.upgradeTitle": "프로로 업그레이드"
}

View File

@@ -0,0 +1,345 @@
{
"sidebar.recent": "Recent",
"sidebar.labels": "Etiketten",
"sidebar.clearFilter": "Filter verwijderen",
"sidebar.sortAlpha": "Sortering A → Z",
"sidebar.sharedNotebookBadge": "· delen",
"notes.deleted": "Opmerking verwijderd",
"notes.deleteFailed": "Kan notitie niet verwijderen",
"notes.recent": "Recent",
"notes.metadataPanel": "Metagegevens",
"notes.historyDisabledTitle": "Versiegeschiedenis",
"notes.historyEnabledTitle": "Geschiedenis geactiveerd!",
"notes.historyEnabledDesc": "Versies van deze notitie worden nu opgeslagen.",
"notes.suggestTitle": "AI-titel",
"notes.generateTitleFromImage": "Genereer titel uit afbeelding",
"notes.titleGenerated": "Gegenereerde titel",
"notes.content": "Inhoud",
"notes.restore": "Herstellen",
"notes.createFailed": "Kan notitie niet maken",
"notes.updateFailed": "Update mislukt",
"notes.archived": "Gearchiveerde notitie",
"notes.archiveFailed": "Archiveren is mislukt",
"notes.sort": "Soort",
"notes.confirmDeleteTitle": "Beoordeling verwijderen",
"notes.leftShare": "Deel verwijderd",
"notes.ideaOrigin": "Oorsprong van het idee",
"notes.noNoteLink": "Puur generatief idee",
"notes.dismiss": "Niet relevant",
"notes.dismissed": "Opmerking verwijderd uit recent",
"notes.generalNotes": "Algemene opmerkingen",
"notes.typeRichText": "Rijke tekst",
"notes.typeChecklist": "To-do-lijst",
"notes.convertedToRichText": "Geconverteerd naar rijke tekst",
"notes.conversionFailed": "Conversie mislukt, blijft in Markdown",
"labels.title": "Etiketten",
"labels.filter": "Filter op tag",
"labels.manage": "Beheer etiketten",
"labels.manageTooltip": "Beheer etiketten",
"labels.delete": "VERWIJDEREN",
"labels.deleteTooltip": "Etiket verwijderen",
"labels.newLabelPlaceholder": "Maak een nieuw etiket",
"labels.namePlaceholder": "Voer de labelnaam in",
"labels.createLabel": "Maak een etiket",
"labels.labelName": "Labelnaam",
"labels.labelColor": "Etiketkleur",
"labels.manageLabels": "Beheer etiketten",
"labels.manageLabelsDescription": "Tags voor deze notitie toevoegen of verwijderen. Klik op een label om de kleur ervan te wijzigen.",
"labels.selectedLabels": "Geselecteerde etiketten",
"labels.filterByLabel": "Filter op tag",
"labels.tagAdded": "'{tag}'-tag toegevoegd",
"labels.showLess": "Zie minder",
"labels.showMore": "Zie meer",
"labels.editLabels": "Etiketten bewerken",
"labels.editLabelsDescription": "Creëer, wijzig kleuren of verwijder labels.",
"labels.noLabelsFound": "Geen tags gevonden.",
"labels.loading": "Laden...",
"labels.notebookRequired": "⚠️ Etiketten zijn alleen verkrijgbaar in notitieboekjes. Verplaats deze notitie eerst naar een notitieboekje.",
"labels.count": "{count} labels",
"ai.chatTab": "Discussie",
"ai.chatPanelContext": "Context",
"ai.contextLabel": "Context",
"ai.contextSourceHeading": "Contextbron",
"ai.tones.professional": "Professioneel",
"ai.tones.creative": "Creatief",
"ai.tones.academic": "Academisch",
"ai.tones.casual": "Ontspannen",
"ai.noImagesError": "Geen afbeeldingen in deze notitie",
"ai.overview": "Samenvatting",
"ai.action.describeImages": "Beschrijf de afbeeldingen",
"ai.generateTitleFromImage": "Genereer titel uit afbeelding",
"ai.titleGenerated": "Titel gegenereerd op basis van afbeelding",
"ai.pptxDownloadButton": "Download .pptx",
"memoryEcho.overlay.sortRecent": "Recent",
"notification.accept": "Accepteren",
"notification.accepted": "Delen geaccepteerd",
"notification.decline": "Weigeren",
"notification.noNotifications": "Geen meldingen",
"notification.downloadPptx": "Download .pptx",
"nav.home": "Welkom",
"nav.recent": "Recent",
"nav.proPlan": "Pro-plan",
"nav.chat": "AI Kat",
"settings.account": "Rekening",
"settings.themeBaseGroup": "Weergave",
"settings.themePalettesGroup": "Kleurenpaletten",
"settings.themeSepia": "Sepia",
"settings.themeMidnight": "Middernacht",
"settings.themeGreen": "Groente",
"settings.themeLavender": "Lavendel",
"settings.themeSand": "Zand",
"settings.themeOcean": "Oceaan",
"settings.themeSunset": "Zonsondergang",
"settings.themeBlue": "Blauw",
"settings.cardSizeMode": "Let op maat",
"settings.cardSizeModeDescription": "Kies tussen bankbiljetten van verschillende of uniforme formaten",
"settings.selectCardSizeMode": "Selecteer weergavemodus",
"settings.cardSizeVariable": "Variabele maten (klein/middelgroot/groot)",
"settings.cardSizeUniform": "Uniforme maat",
"aiSettings.title": "AI",
"aiSettings.providerOpenAI": "OpenAI (wolk)",
"notebook.labels": "Tags:",
"notebook.generatingDescription": "Even geduld a.u.b....",
"admin.chat": "AI Kat",
"admin.ai.chatProvider": "Chatprovider",
"admin.ai.provider": "Leverancier",
"admin.ai.baseUrl": "Basis-URL",
"admin.ai.model": "Model",
"admin.ai.apiKey": "API-sleutel",
"admin.ai.providerOllamaOption": "🦙 Ollama (lokaal en gratis)",
"admin.ai.providerCustomOption": "🔧 Aangepaste OpenAI-compatibel",
"admin.email.status": "Servicestatus",
"admin.email.keySet": "geconfigureerde sleutel",
"admin.email.activeAuto": "Automatische modus: Opnieuw verzenden wordt als prioriteit gebruikt, SMTP als back-up.",
"admin.email.activeSmtp": "Automatische modus: SMTP wordt gebruikt (opnieuw verzenden niet geconfigureerd).",
"admin.email.noneConfigured": "Geen e-mailservice geconfigureerd. Configureer Opnieuw verzenden of SMTP.",
"admin.email.activeProvider": "Actieve leverancier",
"admin.email.testOk": "test geslaagd",
"admin.email.testFail": "mislukte proef",
"admin.smtp.host": "Gastheer",
"admin.users.tierUpdateSuccess": "Abonnement bijgewerkt naar {tier}",
"admin.users.tierUpdateFailed": "Update van abonnement mislukt",
"admin.users.table.subscription": "Abonnement",
"admin.aiTest.provider": "Leverancier :",
"admin.aiTest.model": "Model:",
"admin.aiTest.tipTitle": "Truc:",
"admin.sidebar.dashboard": "Dashboard",
"admin.sidebar.chat": "AI Kat",
"admin.tools.title": "Hulpmiddelen voor agenten",
"admin.tools.brave": "Brave Search-API",
"admin.tools.searxngUrl": "SearXNG-URL",
"admin.dashboard.title": "Dashboard",
"about.platform": "Platform",
"about.technology.frontend": "Front-end",
"about.technology.backend": "Achterkant",
"about.technology.database": "Database",
"about.technology.ai": "AI",
"about.technology.ui": "Interface",
"about.support.feedback": "Opmerkingen",
"support.hostingServers": "Hosting en servers:",
"dataManagement.title": "Gegevens",
"appearance.selectTheme": "Selecteer thema",
"appearance.fontInterDefault": "Inter (standaard)",
"usageMeter.packName": "AI-ontdekkingspakket",
"usageMeter.featureSearch": "Onderzoek",
"usageMeter.featureTags": "Etiketten",
"usageMeter.featureTitles": "Effecten",
"usageMeter.unlimited": "Onbeperkt",
"usageMeter.remaining": "{count} resterend",
"usageMeter.upgradeTitle": "Ga Pro",
"usageMeter.upgradeDescription": "Je hebt alle credits uit het AI-ontdekkingspakket gebruikt. Upgrade naar Pro voor hogere limieten en extra functies.",
"usageMeter.proIncludes": "Pro omvat:",
"usageMeter.proSearch": "100 semantische zoekopdrachten / maand",
"usageMeter.proTags": "200 automatische labels / maand",
"usageMeter.proTitles": "200 autotitels / maand",
"usageMeter.proReformulate": "50 herformuleringen / maand",
"usageMeter.proChat": "100 chatberichten / maand",
"usageMeter.later": "Later",
"usageMeter.upgradePricing": "Ga Pro",
"usageMeter.addApiKey": "Gebruik uw eigen API-sleutel (BYOK)",
"generalSettings.title": "Generaals",
"testPages.titleSuggestions.status": "Status:",
"footer.privacy": "Vertrouwelijkheid",
"documentInfo.tabInfo": "Info",
"languages.targets.chinese": "Chinese",
"agents.searchPlaceholder": "Zoek een makelaar...",
"agents.filterAll": "Alle",
"agents.newBadge": "Nieuw",
"agents.noResults": "Geen enkele agent komt overeen met uw zoekopdracht.",
"agents.types.scraper": "Wachter",
"agents.types.excalidrawGenerator": "Diagram",
"agents.form.slideThemes.bohemian": "Bohemen",
"agents.form.inbox": "Postvak IN",
"agents.form.includeImages": "Voeg afbeeldingen toe",
"agents.form.includeImagesHint": "Extraheer afbeeldingen van geschraapte pagina's en voeg ze toe aan de gegenereerde notitie",
"agents.form.back": "Rug",
"agents.schedule.nextRun": "Volgende uitvoering",
"agents.schedule.pending": "Wachten om te activeren",
"agents.schedule.time": "Uur",
"agents.schedule.dayOfWeek": "Dag van de week",
"agents.schedule.dayOfMonth": "Dag van de maand",
"agents.schedule.days.mon": "Maandag",
"agents.schedule.days.tue": "Dinsdag",
"agents.schedule.days.wed": "Woensdag",
"agents.schedule.days.thu": "DONDERDAG",
"agents.schedule.days.fri": "Vrijdag",
"agents.schedule.days.sat": "ZATERDAG",
"agents.schedule.days.sun": "Zondag",
"agents.toasts.autoRunSuccess": "Agent \"{name}\" is automatisch succesvol uitgevoerd",
"agents.toasts.autoRunError": "Agent '{name}' is mislukt tijdens autorun",
"agents.templates.veilleAI.name": "AI-monitoring",
"agents.templates.veilleTech.name": "Tech-horloge",
"agents.templates.veilleDev.name": "Ontwikkelaar kijken",
"agents.tools.title": "Hulpmiddelen voor agenten",
"agents.tools.configNeeded": "Systeemvereisten",
"agents.help.howToUseContent": "1. Klik op **\"Nieuwe agent\"** (of begin met een **Sjabloon** onderaan de pagina)\n2. Kies een **agenttype** (Onderzoeker, Watcher, Overseer, Custom)\n3. Geef het een **naam** en vul de typespecifieke velden in\n4. Kies eventueel een **doelnotitieboekje** of sla de resultaten op\n5. Selecteer een **frequentie** (Handmatig = u voert het zelf uit)\n6. Klik op **Aanmaken** en druk vervolgens op de knop **Uitvoeren** op de agentkaart\n7. Eenmaal voltooid, verschijnt er een nieuwe notitie in uw doelnotitieboekje",
"agents.help.advancedContent": "Klik op **\"Geavanceerde modus\"** onderaan het formulier om toegang te krijgen tot aanvullende instellingen.\n\n### AI-instructies\n\nMet dit veld kunt u **de standaardsysteemprompt** van de agent overschrijven. Als u dit leeg laat, gebruikt de agent een automatische prompt die is aangepast aan zijn type.\n\n**Waarom het gebruiken?** U wilt het gedrag van de agent precies controleren. Bijvoorbeeld:\n- “Schrijf de samenvatting in het Engels, ook al zijn de bronnen in het Frans”\n- “Structuur de notitie met de secties: Context, Kernpunten, Persoonlijke mening”\n- “Negeer artikelen ouder dan 30 dagen en focus op recent nieuws”\n- \"Biedt voor elk gedetecteerd thema 3 mogelijkheden voor diepgaande studie met links\"\n\n> **Opmerking:** Uw instructies vervangen de standaardinstructies, niet dat ze er iets aan toevoegen.\n\n### Maximale iteraties\n\nDit is het **maximale aantal cycli** dat de agent kan uitvoeren. Eén cyclus = de agent denkt na, roept een tool aan, leest het resultaat en besluit vervolgens over de volgende actie.\n\n- **3-5 iteraties:** voor eenvoudige taken (scrapen van één pagina)\n- **10 iteraties (standaard):** goede balans voor de meeste gevallen\n- **15-25 iteraties:** voor diepgaande zoekopdrachten waarbij de agent verschillende wegen moet verkennen\n\n> **Let op:** Meer iteraties = meer tijd en mogelijk meer API-kosten.",
"agents.help.frequencyContent": "| Frequentie | Gedrag\n|---------------|------------\n| **Handmatig** | U klikt op \"Uitvoeren\" - geen automatische planning\n| **Elk uur** | Rijdt elk uur\n| **Dagelijks** | Wordt één keer per dag uitgevoerd\n| **Wekelijks** | Wordt één keer per week uitgevoerd\n| **Maandelijks** | Wordt één keer per maand uitgevoerd\n\n> **Tip:** Begin met \"Handmatig\" om uw agent te testen en schakel vervolgens over naar de automatische frequentie zodra u tevreden bent.",
"agents.help.targetNotebookContent": "Wanneer een agent zijn taak voltooit, **maakt hij een notitie**. Het **doelnotitieboekje** bepaalt waar ze heen gaat:\n\n- **Inbox** (standaard) — de notitie wordt in uw algemene notities geplaatst\n- **Specifiek notitieboekje** — kies een notitieboekje om de resultaten georganiseerd te houden\n\n> **Tip:** Maak een speciaal notitieboekje zoals “Agent Reports” om alle geautomatiseerde inhoud te centraliseren.",
"chat.timeoutWarning": "De reactie duurt langer dan verwacht...",
"labHeader.live": "Direct",
"labHeader.rename": "Hernoemen",
"richTextEditor.slashCatMedia": "Media",
"richTextEditor.imageUrlPlaceholder": "https://example.com/image.png",
"richTextEditor.slashDiagram": "Diagram",
"richTextEditor.slashSuperscript": "Exposant",
"richTextEditor.superscript": "Exposant",
"brainstorm.title": "Gedachte golven",
"brainstorm.subtitle": "Vergroot de dimensies van potentieel",
"brainstorm.placeholder": "Voer een concept in om te verkennen...",
"brainstorm.generating": "AI oogst zaden van gedachten...",
"brainstorm.newBrainstorm": "Nieuwe brainstorm",
"brainstorm.noSessions": "Nog geen brainstormsessies",
"brainstorm.startOne": "Om te beginnen",
"brainstorm.sessions": "Brainstormsessies",
"brainstorm.seedLabel": "Bron idee",
"brainstorm.brainstormThisIdea": "Brainstorm over dit idee",
"brainstorm.startBrainstorm": "Start de brainstorm",
"brainstorm.spatialMode": "Ruimteverkenningsmodus",
"brainstorm.wave1": "Golf 1",
"brainstorm.wave2": "Golf 2",
"brainstorm.wave3": "Golf 3",
"brainstorm.export": "Exporteren",
"brainstorm.exporting": "Exporteren...",
"brainstorm.wave": "Golf",
"brainstorm.novelty": "Originaliteit",
"brainstorm.originConnection": "Link met herkomst",
"brainstorm.linkedNotes": "Gerelateerde opmerkingen",
"brainstorm.deepen": "Graven",
"brainstorm.deepening": "Generatie...",
"brainstorm.extract": "Maak een notitie",
"brainstorm.converting": "Conversie...",
"brainstorm.dismiss": "Niet relevant",
"brainstorm.noteCreated": "Notitie gemaakt",
"brainstorm.ideas": "ideeën",
"brainstorm.cancel": "Annuleren",
"brainstorm.delete": "VERWIJDEREN",
"brainstorm.ideaOrigin": "Oorsprong van het idee",
"brainstorm.noNoteLink": "Puur generatief idee",
"brainstorm.derived_from": "Afgeleid van",
"brainstorm.opposes": "In tegenstelling tot",
"brainstorm.extends": "Verlengt",
"brainstorm.synthesizes": "Synthetiseer",
"brainstorm.transposes": "Transponeren",
"brainstorm.none_found": "Geen koppeling",
"brainstorm.viewNote": "Zie opmerking",
"brainstorm.addIdea": "Voeg een idee toe",
"brainstorm.manualIdeaPrompt": "Titel van uw idee:",
"brainstorm.invite": "Uitnodiging",
"brainstorm.linkCopied": "Uitnodigingslink gekopieerd!",
"brainstorm.aiIdea": "AI",
"brainstorm.shareDialogTitle": "Deel de brainstorm",
"brainstorm.shareSearchLabel": "Zoek een persoon",
"brainstorm.shareNameOrEmailPlaceholder": "Naam of e-mailadres…",
"brainstorm.shareSubmit": "Deel",
"brainstorm.shareSubmitting": "Verzenden…",
"brainstorm.shareFooterHint": "De persoon ontvangt een melding om te accepteren of te weigeren.",
"brainstorm.sharePublicLink": "Openbare link",
"brainstorm.shareGuestsCanEdit": "Laat gasten bewerken",
"brainstorm.feedbackInviteSent": "Uitnodiging verzonden!",
"brainstorm.feedbackInviteResent": "Uitnodiging terug!",
"brainstorm.feedbackAlreadyShared": "Deze persoon heeft al toegang tot deze brainstorm.",
"brainstorm.feedbackAlreadyPending": "Er is al een uitnodiging in behandeling voor deze persoon.",
"brainstorm.feedbackGenericError": "Fout",
"brainstorm.unnamedPerson": "Naamloos",
"brainstorm.canvasEditTitleReply": "Antwoord",
"brainstorm.canvasEditTitleNewIdea": "Nieuw idee",
"brainstorm.canvasPlaceholderReply": "Jouw antwoord…",
"brainstorm.canvasPlaceholderIdea": "Jouw idee…",
"brainstorm.canvasShortcutSave": "redden",
"brainstorm.canvasShortcutCancel": "Annuleren",
"brainstorm.canvasChildBranch": "kind",
"brainstorm.canvasDoubleClickHint": "Dubbelklik om een idee toe te voegen",
"brainstorm.ideaDetailConnection": "Verbinding",
"brainstorm.ideaDetailNovelty": "Originaliteit",
"brainstorm.ideaDetailWave": "Golf",
"brainstorm.waveFlavorAnalogy": "Analogie",
"brainstorm.liveCollaborationTitle": "Live samenwerking",
"brainstorm.liveStatus": "Live",
"brainstorm.liveYouMarker": "(JIJ)",
"brainstorm.liveOtherParticipants": "{count} andere deelnemers",
"brainstorm.guestReadOnlyNotice": "Je bekijkt deze brainstorm als gast. Log in om te bewerken.",
"brainstorm.impactNotesEnriched": "{count} verrijkte notitie(s)",
"brainstorm.impactNotesMarkedDry": "{count} notitie(s) gemarkeerd als droog",
"brainstorm.exportNotebookPrefix": "Notitieboekje :",
"brainstorm.playbackStep": "Stap {current}/{total}",
"brainstorm.playbackStepsCount": "{count} stappen",
"brainstorm.playbackReturnToLive": "Keer terug om te leven",
"brainstorm.canvasWaitingHint": "Het canvas wacht op jouw vonk...",
"brainstorm.seedNodeBadge": "ZAAD",
"brainstorm.originalSeedDescription": "Eerste bronidee",
"brainstorm.convertedToNoteStatus": "Omgerekend naar beoordeling",
"brainstorm.toastExpandSuccess": "Uitgebreide ideeën!",
"brainstorm.toastExpandFailed": "Mislukking van de uitbreiding",
"brainstorm.toastDismissSuccess": "Idee afgewezen",
"brainstorm.toastDismissFailed": "Gat-mislukking",
"brainstorm.toastConvertSuccess": "Idee omgezet in notitie!",
"brainstorm.toastConvertFailed": "Conversie mislukt",
"brainstorm.toastExportNoteSuccess": "Geëxporteerd als een notitie!",
"brainstorm.toastExportFailed": "Exporteren is mislukt",
"brainstorm.legendSeed": "Zaad",
"brainstorm.legendDisruptions": "Uiteenvallen",
"brainstorm.exportFailedMessage": "Exporteren is mislukt",
"brainstorm.exportDefaultNoteTitle": "Synthese",
"brainstorm.exportOpening": "Opening…",
"brainstorm.ownerBadge": "Eigenaar",
"brainstorm.waveBadge": "Golf {wave}",
"byokSettings.title": "Uw API-sleutels (BYOK)",
"byokSettings.description": "Verbind uw eigen leverancierssleutels om Discovery Pack-quota te omzeilen. Sleutels worden in rust gecodeerd.",
"byokSettings.badgeActive": "BYOK actief",
"byokSettings.tierRequired": "BYOK vereist een Pro-abonnement of hoger.",
"byokSettings.provider": "Leverancier",
"byokSettings.providerPlaceholder": "Kies een leverancier",
"byokSettings.alias": "Formulering (optioneel)",
"byokSettings.aliasPlaceholder": "ex. OpenAI pro",
"byokSettings.apiKey": "API-sleutel",
"byokSettings.save": "Sleutel opslaan",
"byokSettings.saved": "Geregistreerde API-sleutel",
"byokSettings.deleted": "API-sleutel verwijderd",
"byokSettings.error": "Kan sleutel niet registreren",
"byokSettings.loadError": "Kan sleutels niet laden",
"byokSettings.loading": "Laden...",
"byokSettings.empty": "Geen API-sleutel geconfigureerd.",
"byokSettings.confirmDelete": "Deze API-sleutel definitief verwijderen?",
"billing.proAnnualPrice": "€ 99",
"billing.businessAnnualPrice": "€ 299",
"billing.enterpriseTitle": "Bedrijf",
"landing.pricing.perUser": "+ 3,90€/gebruiker",
"landing.pricing.perUserAnnual": "+ 2,90€/gebruiker, jaarlijks gefactureerd",
"landing.pricing.business.feature1": "BYOK (13 leveranciers)",
"landing.pricing.enterprise.feature4": "Toegewijde ondersteuning",
"landing.pricing.enterprise.feature5": "Live onboarding",
"landing.footer.product.title": "Product",
"landing.footer.community.title": "Gemeenschap",
"ai.featureLocked": "Deze functie vereist het PRO-abonnement of hoger.",
"ai.quotaExceeded": "Maandelijkse limiet bereikt. Reset volgende maand.",
"profile.tab": "Profiel",
"about.tab": "Over",
"appearance.tab": "Weergave",
"billing.tab": "Facturering",
"usageMeter.featureChat": "AI-berichten",
"usageMeter.featureReformulate": "Herschrijvingen",
"usageMeter.featureBrainstormCreate": "Brainstorm-aanmaak",
"usageMeter.featureBrainstormExpand": "Brainstorm-uitbreidingen",
"usageMeter.featureBrainstormEnrich": "Brainstorm-verrijkingen"
}

View File

@@ -0,0 +1,289 @@
{
"sidebar.clearFilter": "Usuń filtr",
"sidebar.sortAlpha": "Sortowanie A → Z",
"sidebar.sharedNotebookBadge": "· dzielenie się",
"notes.deleted": "Uwaga usunięta",
"notes.deleteFailed": "Nie udało się usunąć notatki",
"notes.historyDisabledTitle": "Historia wersji",
"notes.historyEnabledTitle": "Historia aktywowana!",
"notes.historyEnabledDesc": "Wersje tej notatki zostaną teraz zapisane.",
"notes.suggestTitle": "Tytuł AI",
"notes.generateTitleFromImage": "Wygeneruj tytuł z obrazu",
"notes.titleGenerated": "Wygenerowany tytuł",
"notes.content": "Treść",
"notes.restore": "Przywrócić",
"notes.createFailed": "Nie można utworzyć notatki",
"notes.updateFailed": "Aktualizacja nie powiodła się",
"notes.archived": "Zarchiwizowana notatka",
"notes.archiveFailed": "Archiwizacja nie powiodła się",
"notes.sort": "Sortować",
"notes.confirmDeleteTitle": "Usuń ocenę",
"notes.leftShare": "Udostępnienie zostało usunięte",
"notes.ideaOrigin": "Pochodzenie pomysłu",
"notes.noNoteLink": "Pomysł czysto twórczy",
"notes.dismiss": "Nie dotyczy",
"notes.dismissed": "Uwaga usunięta z ostatnich",
"notes.generalNotes": "Uwagi ogólne",
"notes.convertedToRichText": "Przekonwertowano na tekst sformatowany",
"notes.conversionFailed": "Konwersja nie powiodła się, pozostaje w Markdown",
"labels.title": "Etykiety",
"labels.filter": "Filtruj według tagu",
"labels.manage": "Zarządzaj etykietami",
"labels.manageTooltip": "Zarządzaj etykietami",
"labels.delete": "USUWAĆ",
"labels.deleteTooltip": "Usuń etykietę",
"labels.newLabelPlaceholder": "Utwórz nową etykietę",
"labels.namePlaceholder": "Wprowadź nazwę etykiety",
"labels.createLabel": "Utwórz etykietę",
"labels.labelName": "Nazwa etykiety",
"labels.labelColor": "Kolor etykiety",
"labels.manageLabels": "Zarządzaj etykietami",
"labels.manageLabelsDescription": "Dodaj lub usuń tagi dla tej notatki. Kliknij etykietę, aby zmienić jej kolor.",
"labels.selectedLabels": "Wybrane etykiety",
"labels.filterByLabel": "Filtruj według tagu",
"labels.tagAdded": "Dodano tag „{tag}”.",
"labels.showLess": "Zobacz mniej",
"labels.showMore": "Zobacz więcej",
"labels.editLabels": "Edytuj etykiety",
"labels.editLabelsDescription": "Twórz, zmieniaj kolory lub usuwaj etykiety.",
"labels.noLabelsFound": "Nie znaleziono tagów.",
"labels.loading": "Załadunek...",
"labels.notebookRequired": "⚠️ Etykiety dostępne są wyłącznie w notesach. Najpierw przenieś tę notatkę do notatnika.",
"ai.chatTab": "Dyskusja",
"ai.contextSourceHeading": "Źródło kontekstu",
"ai.tones.professional": "Profesjonalny",
"ai.tones.creative": "Twórczy",
"ai.tones.academic": "Akademicki",
"ai.tones.casual": "Zrelaksowany",
"ai.noImagesError": "Brak obrazów w tej notatce",
"ai.overview": "Streszczenie",
"ai.action.describeImages": "Opisz obrazy",
"ai.aiCopilot": "Drugi pilot AI",
"ai.generateTitleFromImage": "Wygeneruj tytuł z obrazu",
"ai.titleGenerated": "Tytuł wygenerowany na podstawie obrazu",
"notification.accept": "Przyjąć",
"notification.accepted": "Udostępnienie zaakceptowane",
"notification.decline": "Odmawiać",
"notification.noNotifications": "Brak powiadomień",
"notification.systemNotification": "System",
"settings.themeBaseGroup": "Wyświetlacz",
"settings.themePalettesGroup": "Palety kolorów",
"settings.themeSepia": "Sepia",
"settings.themeMidnight": "Północ",
"settings.themeGreen": "Zielony",
"settings.themeLavender": "Lawenda",
"settings.themeSand": "Piasek",
"settings.themeOcean": "Ocean",
"settings.themeSunset": "Zachód słońca",
"settings.themeBlue": "Niebieski",
"settings.cardSizeMode": "Rozmiar notatki",
"settings.cardSizeModeDescription": "Wybieraj pomiędzy nutami o różnych lub jednakowych rozmiarach",
"settings.selectCardSizeMode": "Wybierz tryb wyświetlania",
"settings.cardSizeVariable": "Różne rozmiary (mały/średni/duży)",
"settings.cardSizeUniform": "Jednolity rozmiar",
"aiSettings.title": "AI",
"notebook.generatingDescription": "Proszę czekać...",
"admin.ai.model": "Model",
"admin.email.status": "Stan usługi",
"admin.email.keySet": "skonfigurowany klucz",
"admin.email.activeAuto": "Tryb automatyczny: Ponowne wysłanie będzie traktowane jako priorytet, SMTP jako kopia zapasowa.",
"admin.email.activeSmtp": "Tryb automatyczny: używany będzie SMTP (ponowne wysyłanie nie jest skonfigurowane).",
"admin.email.noneConfigured": "Nie skonfigurowano żadnej usługi e-mail. Skonfiguruj wysyłanie ponownie lub SMTP.",
"admin.email.activeProvider": "Aktywny dostawca",
"admin.email.testOk": "test zaliczony",
"admin.email.testFail": "nieudany test",
"admin.smtp.host": "Gospodarz",
"admin.users.tierUpdateSuccess": "Subskrypcja zaktualizowana do {tier}",
"admin.users.tierUpdateFailed": "Aktualizacja subskrypcji nie powiodła się",
"admin.users.table.subscription": "Prenumerata",
"admin.aiTest.model": "Modelka:",
"admin.tools.searxng": "SearXNG (własny hosting)",
"admin.tools.brave": "Odważne wyszukiwanie API",
"about.technology.frontend": "Front-end",
"about.technology.backend": "Zaplecze",
"about.technology.ai": "sztuczna inteligencja",
"about.technology.ui": "Interfejs",
"dataManagement.title": "Dane",
"appearance.selectTheme": "Wybierz motyw",
"appearance.fontInterDefault": "Inter (domyślny)",
"usageMeter.packName": "Pakiet odkrywania sztucznej inteligencji",
"usageMeter.featureSearch": "Badania",
"usageMeter.featureTags": "Etykiety",
"usageMeter.featureTitles": "Papiery wartościowe",
"usageMeter.unlimited": "Nieograniczony",
"usageMeter.remaining": "Pozostało: {count}",
"usageMeter.upgradeTitle": "Przejdź na zawodowstwo",
"usageMeter.upgradeDescription": "Wykorzystałeś wszystkie kredyty z pakietu odkrywczego AI. Przejdź na wersję Pro, aby uzyskać wyższe limity i dodatkowe funkcje.",
"usageMeter.proIncludes": "Profesjonalne obejmuje:",
"usageMeter.proSearch": "100 wyszukiwań semantycznych / miesiąc",
"usageMeter.proTags": "200 etykiet samochodowych / miesiąc",
"usageMeter.proTitles": "200 tytułów samochodów / miesiąc",
"usageMeter.proReformulate": "50 przeformułowań/miesiąc",
"usageMeter.proChat": "100 wiadomości na czacie / miesiąc",
"usageMeter.later": "Później",
"usageMeter.upgradePricing": "Przejdź na zawodowstwo",
"usageMeter.addApiKey": "Użyj własnego klucza API (BYOK)",
"generalSettings.title": "Generalicja",
"testPages.titleSuggestions.status": "Stan:",
"agents.searchPlaceholder": "Znajdź agenta...",
"agents.filterAll": "Wszystko",
"agents.newBadge": "Nowy",
"agents.noResults": "Żaden agent nie pasuje do Twojego wyszukiwania.",
"agents.types.scraper": "Stróż",
"agents.types.excalidrawGenerator": "Diagram",
"agents.form.includeImages": "Dołącz obrazy",
"agents.form.includeImagesHint": "Wyodrębnij obrazy ze zeskrobanych stron i dołącz je do wygenerowanej notatki",
"agents.form.back": "Z powrotem",
"agents.schedule.nextRun": "Następna egzekucja",
"agents.schedule.pending": "Oczekiwanie na uruchomienie",
"agents.schedule.time": "Godzina",
"agents.schedule.dayOfWeek": "Dzień tygodnia",
"agents.schedule.dayOfMonth": "Dzień miesiąca",
"agents.schedule.days.mon": "Poniedziałek",
"agents.schedule.days.tue": "Wtorek",
"agents.schedule.days.wed": "Środa",
"agents.schedule.days.thu": "CZWARTEK",
"agents.schedule.days.fri": "Piątek",
"agents.schedule.days.sat": "SOBOTA",
"agents.schedule.days.sun": "Niedziela",
"agents.toasts.autoRunSuccess": "Agent „{name}” został automatycznie uruchomiony pomyślnie",
"agents.toasts.autoRunError": "Agent „{name}” nie powiódł się podczas automatycznego uruchamiania",
"agents.help.howToUseContent": "1. Kliknij **„Nowy agent”** (lub zacznij od **Szablon** na dole strony)\n2. Wybierz **typ agenta** (Badacz, Obserwator, Nadzorca, Niestandardowy)\n3. Nadaj mu **nazwę** i wypełnij pola specyficzne dla typu\n4. Opcjonalnie wybierz **notatnik docelowy** lub zapisz wyniki\n5. Wybierz **częstotliwość** (ręcznie = uruchamiasz samodzielnie)\n6. Kliknij **Utwórz**, a następnie naciśnij przycisk **Wykonaj** na karcie agenta\n7. Po zakończeniu w docelowym notatniku pojawi się nowa notatka",
"agents.help.advancedContent": "Kliknij **„Tryb zaawansowany”** na dole formularza, aby uzyskać dostęp do dodatkowych ustawień.\n\n### Instrukcje AI\n\nTo pole umożliwia **zastąpienie domyślnego monitu systemowego** agenta. Jeżeli pozostawisz to pole puste, agent użyje automatycznego podpowiedzi dostosowanego do jego typu.\n\n**Po co go używać?** Chcesz dokładnie kontrolować zachowanie agenta. Na przykład:\n- „Napisz streszczenie w języku angielskim, nawet jeśli źródła są w języku francuskim”\n- „Ułóż notatkę w oparciu o sekcje: Kontekst, Kluczowe punkty, Osobista opinia”\n- „Ignoruj artykuły starsze niż 30 dni i skup się na najnowszych wiadomościach”\n- „Dla każdego wykrytego tematu oferuje 3 ścieżki dogłębnej analizy z linkami”\n\n> **Uwaga:** Twoje instrukcje zastępują instrukcje domyślne, a nie tylko je uzupełniają.\n\n### Maksymalna liczba iteracji\n\nJest to **maksymalna liczba cykli**, jaką agent może wykonać. Jeden cykl = agent myśli, wywołuje narzędzie, odczytuje wynik, po czym decyduje o kolejnym działaniu.\n\n- **3-5 iteracji:** dla prostych zadań (skrobanie pojedynczej strony)\n- **10 iteracji (domyślnie):** dobra równowaga w większości przypadków\n- **1525 iteracji:** w przypadku głębokich wyszukiwań, w których agent musi zbadać kilka możliwości\n\n> **Uwaga:** Więcej iteracji = więcej czasu i potencjalnie więcej kosztów API.",
"agents.help.frequencyContent": "| Częstotliwość | Zachowanie\n|--------------|------------\n| **Podręcznik** | Klikasz „Uruchom” — brak automatycznego planowania\n| **Co godzinę** | Kursuje co godzinę\n| **Codziennie** | Kursuje raz dziennie\n| **Cotygodniowo** | Kursuje raz w tygodniu\n| **Miesięcznie** | Kursuje raz w miesiącu\n\n> **Wskazówka:** Zacznij od „Ręcznego”, aby przetestować agenta, a następnie przełącz się na częstotliwość automatyczną, gdy będziesz zadowolony.",
"agents.help.targetNotebookContent": "Kiedy agent wykona swoje zadanie, **tworzy notatkę**. **Notatnik docelowy** określa, dokąd zmierza:\n\n- **Skrzynka odbiorcza** (domyślnie) — notatka trafia do notatek ogólnych\n- **Konkretny notatnik** — wybierz notatnik, aby uporządkować wyniki\n\n> **Wskazówka:** Utwórz dedykowany notatnik, taki jak „Raporty agenta”, aby scentralizować całą zautomatyzowaną zawartość.",
"chat.timeoutWarning": "Odpowiedź trwa dłużej, niż oczekiwano…",
"labHeader.rename": "Przemianować",
"richTextEditor.imageUrlPlaceholder": "https://example.com/image.png",
"richTextEditor.slashDiagram": "Diagram",
"brainstorm.title": "Fale myślowe",
"brainstorm.subtitle": "Rozszerz wymiary potencjału",
"brainstorm.placeholder": "Wprowadź koncepcję do odkrycia...",
"brainstorm.generating": "AI zbiera nasiona myśli...",
"brainstorm.newBrainstorm": "Nowa burza mózgów",
"brainstorm.noSessions": "Nie ma jeszcze burzy mózgów",
"brainstorm.startOne": "Aby rozpocząć",
"brainstorm.sessions": "Sesje burzy mózgów",
"brainstorm.seedLabel": "Pomysł źródłowy",
"brainstorm.brainstormThisIdea": "Przemyśl ten pomysł",
"brainstorm.startBrainstorm": "Rozpocznij burzę mózgów",
"brainstorm.spatialMode": "Tryb eksploracji kosmosu",
"brainstorm.wave1": "Fala 1",
"brainstorm.wave2": "Fala 2",
"brainstorm.wave3": "Fala 3",
"brainstorm.export": "Eksport",
"brainstorm.exporting": "Eksport...",
"brainstorm.wave": "Fala",
"brainstorm.novelty": "Oryginalność",
"brainstorm.originConnection": "Link do pochodzenia",
"brainstorm.linkedNotes": "Powiązane uwagi",
"brainstorm.deepen": "Kopać",
"brainstorm.deepening": "Generacja...",
"brainstorm.extract": "Utwórz notatkę",
"brainstorm.converting": "Konwersja...",
"brainstorm.dismiss": "Nie dotyczy",
"brainstorm.noteCreated": "Notatka utworzona",
"brainstorm.ideas": "pomysły",
"brainstorm.cancel": "Anulować",
"brainstorm.delete": "USUWAĆ",
"brainstorm.ideaOrigin": "Pochodzenie pomysłu",
"brainstorm.noNoteLink": "Pomysł czysto twórczy",
"brainstorm.derived_from": "Pochodzi z",
"brainstorm.opposes": "W opozycji do",
"brainstorm.extends": "Rozciąga się",
"brainstorm.synthesizes": "Syntetyzować",
"brainstorm.transposes": "Transponować",
"brainstorm.none_found": "Brak linku",
"brainstorm.viewNote": "Zobacz notatkę",
"brainstorm.addIdea": "Dodaj pomysł",
"brainstorm.manualIdeaPrompt": "Tytuł Twojego pomysłu:",
"brainstorm.invite": "Zapraszać",
"brainstorm.linkCopied": "Link do zaproszenia skopiowany!",
"brainstorm.shareDialogTitle": "Podziel się burzą mózgów",
"brainstorm.shareSearchLabel": "Wyszukaj osobę",
"brainstorm.shareNameOrEmailPlaceholder": "Imię i nazwisko lub e-mail…",
"brainstorm.shareSubmit": "Udział",
"brainstorm.shareSubmitting": "Przesyłka…",
"brainstorm.shareFooterHint": "Osoba otrzyma powiadomienie o konieczności zaakceptowania lub odrzucenia.",
"brainstorm.sharePublicLink": "Link publiczny",
"brainstorm.shareGuestsCanEdit": "Zezwalaj gościom na edycję",
"brainstorm.feedbackInviteSent": "Zaproszenie wysłane!",
"brainstorm.feedbackInviteResent": "Zaproszenie wróciło!",
"brainstorm.feedbackAlreadyShared": "Ta osoba ma już dostęp do tej burzy mózgów.",
"brainstorm.feedbackAlreadyPending": "Zaproszenie dla tej osoby jest już oczekujące.",
"brainstorm.feedbackGenericError": "Błąd",
"brainstorm.unnamedPerson": "Anonimowy",
"brainstorm.canvasEditTitleReply": "Odpowiedź",
"brainstorm.canvasEditTitleNewIdea": "Nowy pomysł",
"brainstorm.canvasPlaceholderReply": "Twoja odpowiedź…",
"brainstorm.canvasPlaceholderIdea": "Twój pomysł…",
"brainstorm.canvasShortcutSave": "ratować",
"brainstorm.canvasShortcutCancel": "Anulować",
"brainstorm.canvasChildBranch": "dziecko",
"brainstorm.canvasDoubleClickHint": "Kliknij dwukrotnie, aby dodać pomysł",
"brainstorm.ideaDetailConnection": "Połączenie",
"brainstorm.ideaDetailNovelty": "Oryginalność",
"brainstorm.ideaDetailWave": "Fala",
"brainstorm.waveFlavorAnalogy": "Analogia",
"brainstorm.liveCollaborationTitle": "Współpraca na żywo",
"brainstorm.liveStatus": "Na żywo",
"brainstorm.liveYouMarker": "(TY)",
"brainstorm.liveOtherParticipants": "{count} innych uczestników",
"brainstorm.guestReadOnlyNotice": "Oglądasz tę burzę mózgów jako gość. Zaloguj się, aby edytować.",
"brainstorm.impactNotesEnriched": "wzbogacone notatki ({count})",
"brainstorm.impactNotesMarkedDry": "{count} notatki oznaczone jako suche",
"brainstorm.exportNotebookPrefix": "Zeszyt :",
"brainstorm.playbackStep": "Krok {current}/{total}",
"brainstorm.playbackStepsCount": "{count} kroków",
"brainstorm.playbackReturnToLive": "Wróć do życia",
"brainstorm.canvasWaitingHint": "Płótno czeka na Twoją iskrę…",
"brainstorm.seedNodeBadge": "NASIONO",
"brainstorm.originalSeedDescription": "Wstępny pomysł na źródło",
"brainstorm.convertedToNoteStatus": "Przekształcone w ocenę",
"brainstorm.toastExpandSuccess": "Rozbudowane pomysły!",
"brainstorm.toastExpandFailed": "Niepowodzenie rozszerzenia",
"brainstorm.toastDismissSuccess": "Pomysł odrzucony",
"brainstorm.toastDismissFailed": "Błąd luki",
"brainstorm.toastConvertSuccess": "Pomysł zamieniony w notatkę!",
"brainstorm.toastConvertFailed": "Konwersja nie powiodła się",
"brainstorm.toastExportNoteSuccess": "Wyeksportowano jako notatkę!",
"brainstorm.toastExportFailed": "Eksport nie powiódł się",
"brainstorm.legendSeed": "Nasienie",
"brainstorm.legendDisruptions": "Rozstania",
"brainstorm.exportFailedMessage": "Eksport nie powiódł się",
"brainstorm.exportDefaultNoteTitle": "Synteza",
"brainstorm.exportOpening": "Otwór…",
"brainstorm.ownerBadge": "Właściciel",
"brainstorm.waveBadge": "Fala {wave}",
"byokSettings.title": "Twoje klucze API (BYOK)",
"byokSettings.description": "Połącz własne klucze dostawców, aby ominąć limity Discovery Pack. Klucze są szyfrowane w stanie spoczynku.",
"byokSettings.badgeActive": "BYOK aktywny",
"byokSettings.tierRequired": "BYOK wymaga subskrypcji Pro lub wyższej.",
"byokSettings.provider": "Dostawca",
"byokSettings.providerPlaceholder": "Wybierz dostawcę",
"byokSettings.alias": "Sformułowanie (opcjonalnie)",
"byokSettings.aliasPlaceholder": "były. OpenAI profesjonalista",
"byokSettings.apiKey": "Klucz API",
"byokSettings.save": "Zapisz klucz",
"byokSettings.saved": "Zarejestrowany klucz API",
"byokSettings.deleted": "Usunięto klucz API",
"byokSettings.error": "Nie można zarejestrować klucza",
"byokSettings.loadError": "Nie można załadować kluczy",
"byokSettings.loading": "Załadunek...",
"byokSettings.empty": "Nie skonfigurowano klucza API.",
"byokSettings.confirmDelete": "Trwale usunąć ten klucz API?",
"billing.enterpriseTitle": "Biznes",
"landing.pricing.perUser": "+ 3,90€/użytkownika",
"landing.pricing.perUserAnnual": "+ 2,90€/użytkownika, rozliczenie roczne",
"ai.featureLocked": "Ta funkcja wymaga planu PRO lub wyższego.",
"ai.quotaExceeded": "Osiągnięto limit miesięczny. Reset w przyszłym miesiącu.",
"profile.tab": "Profil",
"about.tab": "O aplikacji",
"appearance.tab": "Wygląd",
"billing.tab": "Rozliczenia",
"usageMeter.featureChat": "Wiadomości AI",
"usageMeter.featureReformulate": "Przeformułowania",
"usageMeter.featureBrainstormCreate": "Tworzenia brainstorm",
"usageMeter.featureBrainstormExpand": "Rozszerzenia brainstorm",
"usageMeter.featureBrainstormEnrich": "Wzbogacenia brainstorm"
}

View File

@@ -0,0 +1,274 @@
{
"sidebar.clearFilter": "Удалить фильтр",
"sidebar.sharedNotebookBadge": "· обмен",
"notes.deleted": "Примечание удалено.",
"notes.deleteFailed": "Не удалось удалить заметку",
"notes.historyDisabledTitle": "История версий",
"notes.historyEnabledTitle": "История активирована!",
"notes.historyEnabledDesc": "Версии этой заметки теперь будут сохранены.",
"notes.suggestTitle": "AI-заголовок",
"notes.generateTitleFromImage": "Создать заголовок из изображения",
"notes.titleGenerated": "Сгенерированный заголовок",
"notes.content": "Содержание",
"notes.restore": "Восстановить",
"notes.createFailed": "Не удалось создать заметку",
"notes.updateFailed": "Обновление не выполнено",
"notes.archived": "Архивная заметка",
"notes.archiveFailed": "Не удалось архивировать",
"notes.sort": "Сортировать",
"notes.confirmDeleteTitle": "Удалить оценку",
"notes.leftShare": "Поделиться удалено",
"notes.ideaOrigin": "Происхождение идеи",
"notes.noNoteLink": "Чисто генеративная идея",
"notes.dismiss": "Не актуально",
"notes.dismissed": "Примечание удалено из недавних",
"notes.generalNotes": "Общие замечания",
"notes.convertedToRichText": "Преобразовано в форматированный текст",
"notes.conversionFailed": "Конвертация не удалась, остается в Markdown",
"labels.title": "Этикетки",
"labels.filter": "Фильтровать по тегу",
"labels.manage": "Управление ярлыками",
"labels.manageTooltip": "Управление ярлыками",
"labels.delete": "УДАЛИТЬ",
"labels.deleteTooltip": "Удалить ярлык",
"labels.newLabelPlaceholder": "Создать новый ярлык",
"labels.namePlaceholder": "Введите название ярлыка",
"labels.createLabel": "Создать ярлык",
"labels.labelName": "Название этикетки",
"labels.labelColor": "Цвет этикетки",
"labels.manageLabels": "Управление ярлыками",
"labels.manageLabelsDescription": "Добавьте или удалите теги для этой заметки. Нажмите на метку, чтобы изменить ее цвет.",
"labels.selectedLabels": "Выбранные ярлыки",
"labels.filterByLabel": "Фильтровать по тегу",
"labels.tagAdded": "Добавлен тег \"{tag}\"",
"labels.showLess": "Посмотреть меньше",
"labels.showMore": "Посмотреть больше",
"labels.editLabels": "Изменить ярлыки",
"labels.editLabelsDescription": "Создавайте, меняйте цвета или удаляйте метки.",
"labels.noLabelsFound": "Теги не найдены.",
"labels.loading": "Загрузка...",
"labels.notebookRequired": "⚠️Этикетки доступны только в блокнотах. Сначала перенесите эту заметку в блокнот.",
"ai.contextSourceHeading": "Источник контекста",
"ai.tones.professional": "Профессиональный",
"ai.tones.creative": "Креатив",
"ai.tones.academic": "Академический",
"ai.tones.casual": "Расслабленный",
"ai.noImagesError": "В этой заметке нет изображений",
"ai.overview": "Краткое содержание",
"ai.action.describeImages": "Опишите изображения",
"ai.generateTitleFromImage": "Создать заголовок из изображения",
"ai.titleGenerated": "Название создано из изображения",
"notification.accept": "Принимать",
"notification.accepted": "Публикация принята",
"notification.decline": "Мусор",
"notification.noNotifications": "Нет уведомлений",
"settings.themeBaseGroup": "Отображать",
"settings.themePalettesGroup": "Цветовые палитры",
"settings.themeSepia": "Сепия",
"settings.themeMidnight": "Полночь",
"settings.themeGreen": "Зеленый",
"settings.themeLavender": "Лаванда",
"settings.themeSand": "Песок",
"settings.themeOcean": "Океан",
"settings.themeSunset": "Закат",
"settings.themeBlue": "Синий",
"settings.cardSizeMode": "Размер заметки",
"settings.cardSizeModeDescription": "Выбирайте между банкнотами разного или одинакового размера.",
"settings.selectCardSizeMode": "Выберите режим отображения",
"settings.cardSizeVariable": "Различные размеры (маленький/средний/большой)",
"settings.cardSizeUniform": "Единый размер",
"aiSettings.title": "ИИ",
"notebook.generatingDescription": "Пожалуйста, подождите...",
"admin.email.status": "Статус услуги",
"admin.email.keySet": "настроенный ключ",
"admin.email.activeAuto": "Автоматический режим: повторная отправка будет использоваться в качестве приоритета, SMTP — в качестве резервной копии.",
"admin.email.activeSmtp": "Автоматический режим: будет использоваться SMTP (повторная отправка не настроена).",
"admin.email.noneConfigured": "Служба электронной почты не настроена. Настройте повторную отправку или SMTP.",
"admin.email.activeProvider": "Активный поставщик",
"admin.email.testOk": "тест пройден",
"admin.email.testFail": "неудавшийся тест",
"admin.users.tierUpdateSuccess": "Подписка обновлена ​​до {tier}",
"admin.users.tierUpdateFailed": "Обновление подписки не удалось",
"admin.users.table.subscription": "Подписка",
"admin.tools.brave": "API храброго поиска",
"about.technology.ui": "Интерфейс",
"dataManagement.title": "Данные",
"appearance.selectTheme": "Выберите тему",
"appearance.fontInterDefault": "Интер (по умолчанию)",
"usageMeter.packName": "Пакет исследований ИИ",
"usageMeter.featureSearch": "Исследовать",
"usageMeter.featureTags": "Этикетки",
"usageMeter.featureTitles": "Ценные бумаги",
"usageMeter.unlimited": "Безлимитный",
"usageMeter.remaining": "осталось {count}",
"usageMeter.upgradeTitle": "Станьте профессионалом",
"usageMeter.upgradeDescription": "Вы использовали все кредиты из пакета AI Discovery. Обновите версию до Pro, чтобы получить более высокие лимиты и дополнительные функции.",
"usageMeter.proIncludes": "Про включает в себя:",
"usageMeter.proSearch": "100 смысловых поисков/месяц",
"usageMeter.proTags": "200 автоэтикеток/месяц",
"usageMeter.proTitles": "200 наименований автомобилей/месяц",
"usageMeter.proReformulate": "50 переформулировок/месяц",
"usageMeter.proChat": "100 сообщений в чате в месяц",
"usageMeter.later": "Позже",
"usageMeter.upgradePricing": "Станьте профессионалом",
"usageMeter.addApiKey": "Используйте свой собственный ключ API (BYOK)",
"generalSettings.title": "Генералы",
"agents.searchPlaceholder": "Найдите агента...",
"agents.filterAll": "Все",
"agents.newBadge": "Новый",
"agents.noResults": "Ни один агент не соответствует вашему запросу.",
"agents.form.includeImages": "Включить изображения",
"agents.form.includeImagesHint": "Извлекайте изображения из очищенных страниц и прикрепляйте их к созданной заметке.",
"agents.form.back": "Назад",
"agents.schedule.nextRun": "Следующее исполнение",
"agents.schedule.pending": "Ожидание срабатывания",
"agents.schedule.time": "Час",
"agents.schedule.dayOfWeek": "День недели",
"agents.schedule.dayOfMonth": "День месяца",
"agents.schedule.days.mon": "Понедельник",
"agents.schedule.days.tue": "Вторник",
"agents.schedule.days.wed": "Среда",
"agents.schedule.days.thu": "ЧЕТВЕРГ",
"agents.schedule.days.fri": "Пятница",
"agents.schedule.days.sat": "СУББОТА",
"agents.schedule.days.sun": "Воскресенье",
"agents.toasts.autoRunSuccess": "Агент «{name}» успешно запустился автоматически",
"agents.toasts.autoRunError": "Агенту \"{name}\" не удалось выполнить автозапуск.",
"agents.help.howToUseContent": "1. Нажмите **Новый агент** (или начните с **Шаблона** внизу страницы).\n2. Выберите **тип агента** (Исследователь, Наблюдатель, Надзиратель, Пользовательский).\n3. Присвойте ему **имя** и заполните поля для конкретного типа.\n4. При желании выберите **целевой блокнот** или сохраните результаты.\n5. Выберите **частоту** (Вручную = вы запускаете ее самостоятельно)\n6. Нажмите **Создать**, затем нажмите кнопку **Выполнить** на карточке агента.\n7. После завершения в целевом блокноте появится новая заметка.",
"agents.help.advancedContent": "Нажмите **\"Расширенный режим\"** внизу формы, чтобы получить доступ к дополнительным настройкам.\n\n### Инструкции ИИ\n\nЭто поле позволяет вам **переопределить системное приглашение агента по умолчанию**. Если вы оставите это поле пустым, агент будет использовать автоматическое приглашение, адаптированное к его типу.\n\n**Зачем его использовать?** Вы хотите точно контролировать поведение агента. Например:\n- «Напишите резюме на английском языке, даже если источники на французском языке»\n- «Структурируйте заметку по разделам: Контекст, Ключевые моменты, Личное мнение»\n- «Игнорируйте статьи старше 30 дней и сосредоточьтесь на последних новостях»\n- «Для каждой обнаруженной темы предлагается 3 направления углубленного изучения со ссылками»\n\n> **Примечание.** Ваши инструкции заменяют инструкции по умолчанию, а не дополняют их.\n\n### Макс. итераций\n\nЭто **максимальное количество циклов**, которое может выполнить агент. Один цикл = агент думает, вызывает инструмент, считывает результат, затем принимает решение о следующем действии.\n\n- **35 итераций:** для простых задач (парсинг одной страницы).\n- **10 итераций (по умолчанию):** хороший баланс для большинства случаев.\n **1525 итераций**: для глубокого поиска, когда агент должен изучить несколько направлений.\n\n> **Внимание:** Больше итераций = больше времени и, возможно, больше затрат на API.",
"agents.help.frequencyContent": "| Частота | Поведение\n|---------------|------------\n| **Руководство** | Нажимаете «Выполнить» — автоматического планирования нет.\n| **Каждый час** | Работает каждый час\n| **Ежедневно** | Запускается один раз в день\n| **Еженедельно** | Проходит раз в неделю\n| **Ежемесячно** | Проходит раз в месяц\n\n> **Совет.** Начните с варианта «Вручную», чтобы протестировать своего агента, а затем, когда все будет удовлетворено, переключитесь на автоматическую частоту.",
"agents.help.targetNotebookContent": "Когда агент выполняет свою задачу, он **создает заметку**. **Целевой блокнот** определяет, куда она идет:\n\n- **Входящие** (по умолчанию) — заметка попадает в общие заметки.\n- **Особый блокнот** — выберите блокнот, чтобы результаты были систематизированы.\n\n> **Совет.** Создайте специальный блокнот, например «Отчеты агента», чтобы централизовать весь автоматизированный контент.",
"chat.timeoutWarning": "Ответ занимает больше времени, чем ожидалось...",
"labHeader.rename": "Переименовать",
"richTextEditor.imageUrlPlaceholder": "https://example.com/image.png",
"brainstorm.title": "Мысленные волны",
"brainstorm.subtitle": "Расширьте масштабы потенциала",
"brainstorm.placeholder": "Введите концепцию для изучения...",
"brainstorm.generating": "ИИ собирает семена мысли...",
"brainstorm.newBrainstorm": "Новый мозговой штурм",
"brainstorm.noSessions": "Мозговых штурмов пока нет",
"brainstorm.startOne": "Для начала",
"brainstorm.sessions": "Мозговые штурмы",
"brainstorm.seedLabel": "Исходная идея",
"brainstorm.brainstormThisIdea": "Продумайте эту идею",
"brainstorm.startBrainstorm": "Начать мозговой штурм",
"brainstorm.spatialMode": "Режим исследования космоса",
"brainstorm.wave1": "Волна 1",
"brainstorm.wave2": "Волна 2",
"brainstorm.wave3": "Волна 3",
"brainstorm.export": "Экспорт",
"brainstorm.exporting": "Экспорт...",
"brainstorm.wave": "Волна",
"brainstorm.novelty": "Оригинальность",
"brainstorm.originConnection": "Ссылка на происхождение",
"brainstorm.linkedNotes": "Связанные примечания",
"brainstorm.deepen": "Копать",
"brainstorm.deepening": "Поколение...",
"brainstorm.extract": "Создать заметку",
"brainstorm.converting": "Преобразование...",
"brainstorm.dismiss": "Не актуально",
"brainstorm.noteCreated": "Заметка создана",
"brainstorm.ideas": "идеи",
"brainstorm.cancel": "Отмена",
"brainstorm.delete": "УДАЛИТЬ",
"brainstorm.ideaOrigin": "Происхождение идеи",
"brainstorm.noNoteLink": "Чисто генеративная идея",
"brainstorm.derived_from": "Получено из",
"brainstorm.opposes": "В противовес",
"brainstorm.extends": "Расширяет",
"brainstorm.synthesizes": "Синтезировать",
"brainstorm.transposes": "Транспонировать",
"brainstorm.none_found": "Нет ссылки",
"brainstorm.viewNote": "См. примечание",
"brainstorm.addIdea": "Добавить идею",
"brainstorm.manualIdeaPrompt": "Название вашей идеи:",
"brainstorm.invite": "Приглашать",
"brainstorm.linkCopied": "Ссылка-приглашение скопирована!",
"brainstorm.shareDialogTitle": "Поделитесь мозговым штурмом",
"brainstorm.shareSearchLabel": "Поиск человека",
"brainstorm.shareNameOrEmailPlaceholder": "Имя или адрес электронной почты…",
"brainstorm.shareSubmit": "Делиться",
"brainstorm.shareSubmitting": "Отправка…",
"brainstorm.shareFooterHint": "Человек получит уведомление о принятии или отклонении.",
"brainstorm.sharePublicLink": "Публичная ссылка",
"brainstorm.shareGuestsCanEdit": "Разрешить гостям редактировать",
"brainstorm.feedbackInviteSent": "Приглашение отправлено!",
"brainstorm.feedbackInviteResent": "Приглашение вернулось!",
"brainstorm.feedbackAlreadyShared": "У этого человека уже есть доступ к этому мозговому штурму.",
"brainstorm.feedbackAlreadyPending": "Приглашение для этого человека уже находится на рассмотрении.",
"brainstorm.feedbackGenericError": "Ошибка",
"brainstorm.unnamedPerson": "Безымянный",
"brainstorm.canvasEditTitleReply": "Отвечать",
"brainstorm.canvasEditTitleNewIdea": "Новая идея",
"brainstorm.canvasPlaceholderReply": "Ваш ответ…",
"brainstorm.canvasPlaceholderIdea": "Ваша идея…",
"brainstorm.canvasShortcutSave": "сохранять",
"brainstorm.canvasShortcutCancel": "Отмена",
"brainstorm.canvasChildBranch": "ребенок",
"brainstorm.canvasDoubleClickHint": "Дважды щелкните, чтобы добавить идею",
"brainstorm.ideaDetailConnection": "Связь",
"brainstorm.ideaDetailNovelty": "Оригинальность",
"brainstorm.ideaDetailWave": "Волна",
"brainstorm.waveFlavorAnalogy": "Аналогия",
"brainstorm.liveCollaborationTitle": "Живое сотрудничество",
"brainstorm.liveStatus": "Жить",
"brainstorm.liveYouMarker": "(ТЫ)",
"brainstorm.liveOtherParticipants": "{count} других участников",
"brainstorm.guestReadOnlyNotice": "Вы смотрите этот мозговой штурм как гость. Войдите, чтобы редактировать.",
"brainstorm.impactNotesEnriched": "Дополнительные заметки: {count}",
"brainstorm.impactNotesMarkedDry": "Заметки: {count}, помечены как сухие",
"brainstorm.exportNotebookPrefix": "Блокнот :",
"brainstorm.playbackStep": "Шаг {текущий}/{всего}",
"brainstorm.playbackStepsCount": "{count} шагов",
"brainstorm.playbackReturnToLive": "Вернуться к жизни",
"brainstorm.canvasWaitingHint": "Холст ждёт вашей искры…",
"brainstorm.seedNodeBadge": "СЕМЯ",
"brainstorm.originalSeedDescription": "Первоначальная идея",
"brainstorm.convertedToNoteStatus": "Преобразовано в рейтинг",
"brainstorm.toastExpandSuccess": "Расширение идей!",
"brainstorm.toastExpandFailed": "Неудача расширения",
"brainstorm.toastDismissSuccess": "Идея отклонена",
"brainstorm.toastDismissFailed": "Провал провала",
"brainstorm.toastConvertSuccess": "Идея воплощена в заметку!",
"brainstorm.toastConvertFailed": "Преобразование не удалось",
"brainstorm.toastExportNoteSuccess": "Экспортировано как заметка!",
"brainstorm.toastExportFailed": "Экспорт не удался",
"brainstorm.legendSeed": "Семя",
"brainstorm.legendDisruptions": "Расставания",
"brainstorm.exportFailedMessage": "Экспорт не удался",
"brainstorm.exportDefaultNoteTitle": "Синтез",
"brainstorm.exportOpening": "Открытие…",
"brainstorm.ownerBadge": "Владелец",
"brainstorm.waveBadge": "Волна {волна}",
"byokSettings.title": "Ваши ключи API (BYOK)",
"byokSettings.description": "Подключите ключи собственного поставщика, чтобы обойти квоты Discovery Pack. Ключи шифруются в состоянии покоя.",
"byokSettings.badgeActive": "BYOK активен",
"byokSettings.tierRequired": "BYOK требует подписки Pro или выше.",
"byokSettings.provider": "Поставщик",
"byokSettings.providerPlaceholder": "Выберите поставщика",
"byokSettings.alias": "Формулировка (необязательно)",
"byokSettings.aliasPlaceholder": "бывший. OpenAI про",
"byokSettings.apiKey": "API-ключ",
"byokSettings.save": "Сохранить ключ",
"byokSettings.saved": "Зарегистрированный ключ API",
"byokSettings.deleted": "Ключ API удален.",
"byokSettings.error": "Невозможно зарегистрировать ключ",
"byokSettings.loadError": "Невозможно загрузить ключи",
"byokSettings.loading": "Загрузка...",
"byokSettings.empty": "Ключ API не настроен.",
"byokSettings.confirmDelete": "Удалить этот ключ API навсегда?",
"billing.enterpriseTitle": "Бизнес",
"landing.pricing.perUser": "+ 3,90 евро/пользователь",
"landing.pricing.perUserAnnual": "+ 2,90 евро за пользователя, оплата производится ежегодно",
"ai.featureLocked": "Для этой функции требуется план PRO или выше.",
"ai.quotaExceeded": "Достигнут месячный лимит. Сброс в следующем месяце.",
"profile.tab": "Профиль",
"about.tab": "О",
"appearance.tab": "Появление",
"billing.tab": "Биллинг",
"usageMeter.featureChat": "Сообщения ИИ",
"usageMeter.featureReformulate": "Реформулировки",
"usageMeter.featureBrainstormCreate": "Мозговой штурм творений",
"usageMeter.featureBrainstormExpand": "расширения для мозгового штурма",
"usageMeter.featureBrainstormEnrich": "Мозговой штурм"
}

View File

@@ -0,0 +1,259 @@
{
"about.tab": "关于",
"about.technology.ai": "AI",
"aiSettings.title": "人工智能",
"about.technology.ui": "界面",
"admin.ai.providerCustomOption": "🔧 自定义 OpenAI 兼容",
"admin.ai.providerOllamaOption": "🦙Ollama本地且免费",
"admin.email.activeAuto": "自动模式:将首先使用重新发送,然后使用 SMTP 作为后备。",
"admin.email.activeProvider": "活跃的提供商",
"admin.email.activeSmtp": "自动模式:将使用 SMTP未配置重新发送。",
"admin.email.keySet": "按键已配置",
"admin.email.noneConfigured": "未配置电子邮件服务。设置重新发送或 SMTP。",
"admin.email.status": "服务状态",
"admin.email.testFail": "测试失败",
"admin.email.testOk": "测试通过",
"admin.tools.brave": "勇敢的搜索API",
"admin.tools.searxngUrl": "搜索XNG URL",
"admin.users.table.subscription": "订阅",
"admin.users.tierUpdateFailed": "更新订阅失败",
"admin.users.tierUpdateSuccess": "订阅已更新至 {tier}",
"agents.filterAll": "全部",
"agents.form.back": "后退",
"agents.form.includeImages": "包含图像",
"agents.form.includeImagesHint": "从抓取的页面中提取图像并将其附加到生成的注释中",
"agents.help.advancedContent": "单击表单底部的**“高级模式”**以访问其他设置。\n\n###人工智能指令\n\n此字段允许您**替换代理的默认系统提示**。如果留空,代理将使用适合其类型的自动提示。\n\n**为什么使用它?** 您想要精确控制代理的行为方式。例如:\n- “即使来源是法语,也用英语写摘要”\n- “用以下部分构建笔记:背景、要点、个人观点”\n- “忽略超过 30 天的文章并关注最近的新闻”\n- “对于每个检测到的主题,建议 3 个带有链接的后续线索”\n\n> **注意:** 您的说明会替换默认值,但不会添加到默认值中。\n\n### 最大迭代次数\n\n这是代理可以执行的**最大周期数**。一个周期=智能体思考、调用工具、读取结果,然后决定下一步行动。\n\n- **3-5 次迭代:** 对于简单任务(抓取单个页面)\n- **10 次迭代(默认):** 大多数情况下具有良好的平衡性\n- **15-25 次迭代:** 用于代理需要探索多个线索的深入研究\n\n> **警告:** 更多迭代 = 更多时间和潜在更高的 API 成本。",
"agents.help.frequencyContent": "|频率|行为\n|------------|----------\n| **手册** |您自己点击“运行”——没有自动调度\n| **每小时** |每小时运行一次\n| **每日** |每天运行一次\n| **每周** |每周运行一次\n| **每月** |每月运行一次\n\n> **提示:** 从“手动”开始测试您的代理,然后在对结果满意后切换到自动频率。",
"agents.help.howToUseContent": "1. 单击**“新代理”**(或从页面底部的**模板**开始)\n2. 选择**代理类型**(研究员、监控者、观察者、自定义)\n3. 为其命名**并填写特定于类型的字段\n4. 选择一个**目标笔记本**来保存结果\n5. 选择**频率**(手动=您自己触发)\n6. 单击“**创建**”,然后点击代理卡上的“**运行**”按钮\n7. 完成后,目标笔记本中会出现一条新笔记",
"agents.help.targetNotebookContent": "当代理完成其任务时,它**创建一条注释**。 **目标笔记本**决定该笔记的去向:\n\n- **收件箱**(默认)- 注释将转到您的一般注释\n- **特定笔记本** — 选择一个笔记本来整理代理结果\n\n> **提示:** 创建一个专用笔记本(如“代理报告”),将所有自动化内容保存在一个位置。",
"agents.newBadge": "新的",
"agents.noResults": "没有代理符合您的搜索。",
"agents.schedule.dayOfMonth": "一个月中的哪一天",
"agents.schedule.dayOfWeek": "星期几",
"agents.schedule.days.fri": "星期五",
"agents.schedule.days.mon": "周一",
"agents.schedule.days.sat": "周六",
"agents.schedule.days.sun": "星期日",
"agents.schedule.days.thu": "周四",
"agents.schedule.days.tue": "周二",
"agents.schedule.days.wed": "周三",
"agents.schedule.nextRun": "下次运行",
"agents.schedule.pending": "待定触发",
"agents.schedule.time": "时间",
"agents.searchPlaceholder": "搜寻代理...",
"agents.toasts.autoRunError": "代理“{name}”在自动执行期间失败",
"agents.toasts.autoRunSuccess": "代理“{name}”自动成功执行",
"ai.action.describeImages": "描述图像",
"ai.contextSourceHeading": "上下文源",
"ai.featureLocked": "此功能需要 PRO 计划或更高版本。",
"ai.generateTitleFromImage": "从图像生成标题",
"notes.generateTitleFromImage": "从图像生成标题",
"ai.noImagesError": "本笔记中没有图片",
"ai.overview": "概述",
"ai.quotaExceeded": "已达到每月限额。下个月重置。",
"ai.titleGenerated": "从图像生成的标题",
"ai.tones.academic": "学术的",
"ai.tones.casual": "随意的",
"ai.tones.creative": "有创造力的",
"ai.tones.professional": "专业的",
"appearance.fontInterDefault": "国际米兰(默认)",
"appearance.selectTheme": "选择主题",
"appearance.tab": "外貌",
"billing.businessAnnualPrice": "299 欧元",
"billing.businessPrice": "29.90 欧元",
"billing.proAnnualPrice": "99 欧元",
"billing.proPrice": "9.90 欧元",
"billing.tab": "计费",
"brainstorm.addIdea": "添加想法",
"brainstorm.brainstormThisIdea": "集思广益这个想法",
"brainstorm.cancel": "取消",
"brainstorm.canvasChildBranch": "孩子",
"brainstorm.canvasDoubleClickHint": "双击添加想法",
"brainstorm.canvasEditTitleNewIdea": "新想法",
"brainstorm.canvasEditTitleReply": "回复",
"brainstorm.canvasPlaceholderIdea": "你的想法……",
"brainstorm.canvasPlaceholderReply": "你的回复...",
"brainstorm.canvasShortcutCancel": "取消",
"brainstorm.canvasShortcutSave": "节省",
"brainstorm.canvasWaitingHint": "画布正在等待你的火花......",
"brainstorm.convertedToNoteStatus": "转换为注释",
"brainstorm.converting": "转换...",
"brainstorm.deepen": "深化",
"brainstorm.deepening": "生成...",
"brainstorm.delete": "删除",
"brainstorm.derived_from": "源自",
"brainstorm.dismiss": "不相关",
"notes.dismiss": "不相关",
"brainstorm.export": "出口",
"brainstorm.exportDefaultNoteTitle": "合成",
"brainstorm.exportFailedMessage": "导出失败",
"brainstorm.exportNotebookPrefix": "笔记本:",
"brainstorm.exportOpening": "开幕…",
"brainstorm.exporting": "出口...",
"brainstorm.extends": "延伸",
"brainstorm.extract": "创建注释",
"brainstorm.feedbackAlreadyPending": "此人的邀请已待处理。",
"brainstorm.feedbackAlreadyShared": "此人已经可以访问此头脑风暴。",
"brainstorm.feedbackGenericError": "错误",
"brainstorm.feedbackInviteResent": "邀请已重新发送!",
"brainstorm.feedbackInviteSent": "邀请已发送!",
"brainstorm.generating": "人工智能正在收获思想的种子......",
"brainstorm.guestReadOnlyNotice": "您正在以访客身份观看本次头脑风暴。登录进行编辑。",
"brainstorm.ideaDetailConnection": "联系",
"brainstorm.ideaDetailNovelty": "新奇",
"brainstorm.novelty": "新奇",
"brainstorm.ideaDetailWave": "海浪",
"brainstorm.wave": "海浪",
"brainstorm.ideaOrigin": "想法的由来",
"notes.ideaOrigin": "想法的由来",
"brainstorm.ideas": "想法",
"brainstorm.impactNotesEnriched": "丰富了 {count} 个音符",
"brainstorm.impactNotesMarkedDry": "{count} 个音符标记为“干”",
"brainstorm.invite": "邀请",
"brainstorm.legendDisruptions": "干扰",
"brainstorm.legendSeed": "种子",
"brainstorm.linkCopied": "邀请链接已复制!",
"brainstorm.linkedNotes": "链接笔记",
"brainstorm.liveCollaborationTitle": "实时协作",
"brainstorm.liveOtherParticipants": "其他 {count} 名参与者",
"brainstorm.liveStatus": "居住",
"brainstorm.liveYouMarker": "(你)",
"brainstorm.manualIdeaPrompt": "你的想法的标题:",
"brainstorm.newBrainstorm": "新的头脑风暴",
"brainstorm.noNoteLink": "纯粹的生成想法",
"notes.noNoteLink": "纯粹的生成想法",
"brainstorm.noSessions": "还没有集思广益",
"brainstorm.none_found": "没有注释链接",
"brainstorm.noteCreated": "注释已创建",
"brainstorm.opposes": "反对与",
"brainstorm.originConnection": "原点连接",
"brainstorm.originalSeedDescription": "原始种子想法",
"brainstorm.ownerBadge": "所有者",
"brainstorm.placeholder": "输入一个概念来展开...",
"brainstorm.playbackReturnToLive": "返回直播",
"brainstorm.playbackStep": "步骤 {当前}/{总计}",
"brainstorm.playbackStepsCount": "{count} 步",
"brainstorm.seedLabel": "种子想法",
"brainstorm.seedNodeBadge": "种子",
"brainstorm.sessions": "头脑风暴",
"brainstorm.shareDialogTitle": "分享头脑风暴",
"brainstorm.shareFooterHint": "他们将收到接受或拒绝的通知。",
"brainstorm.shareGuestsCanEdit": "允许访客编辑",
"brainstorm.shareNameOrEmailPlaceholder": "姓名或电子邮件...",
"brainstorm.sharePublicLink": "公共链接",
"brainstorm.shareSearchLabel": "找人",
"brainstorm.shareSubmit": "分享",
"brainstorm.shareSubmitting": "正在发送...",
"brainstorm.spatialMode": "空间探索模式",
"brainstorm.startBrainstorm": "开始头脑风暴",
"brainstorm.startOne": "开始一个",
"brainstorm.subtitle": "展现潜力的维度",
"brainstorm.synthesizes": "合成",
"brainstorm.title": "思想的波浪",
"brainstorm.toastConvertFailed": "转换失败",
"brainstorm.toastConvertSuccess": "想法转化为笔记!",
"brainstorm.toastDismissFailed": "驳回失败",
"brainstorm.toastDismissSuccess": "想法被驳回",
"brainstorm.toastExpandFailed": "扩展失败",
"brainstorm.toastExpandSuccess": "想法扩展了!",
"brainstorm.toastExportFailed": "导出失败",
"brainstorm.toastExportNoteSuccess": "导出为注释!",
"brainstorm.transposes": "转置",
"brainstorm.unnamedPerson": "无名",
"brainstorm.viewNote": "查看备注",
"brainstorm.wave1": "第一波",
"brainstorm.wave2": "第2波",
"brainstorm.wave3": "第 3 波",
"brainstorm.waveBadge": "波{波}",
"brainstorm.waveFlavorAnalogy": "类比",
"byokSettings.alias": "标签(可选)",
"byokSettings.aliasPlaceholder": "例如工作开放人工智能",
"byokSettings.apiKey": "API密钥",
"byokSettings.badgeActive": "BYOK 活跃",
"byokSettings.confirmDelete": "永久删除此 API 密钥吗?",
"byokSettings.deleted": "API 密钥已删除",
"byokSettings.description": "连接您自己的 LLM 提供商密钥以绕过 Discovery Pack 配额。密钥在静态时被加密。",
"byokSettings.empty": "尚未配置 API 密钥。",
"byokSettings.error": "无法保存 API 密钥",
"byokSettings.loadError": "无法加载 API 密钥",
"byokSettings.loading": "正在加载密钥...",
"byokSettings.provider": "提供者",
"byokSettings.providerPlaceholder": "选择提供商",
"byokSettings.save": "保存密钥",
"byokSettings.saved": "API 密钥已保存",
"byokSettings.tierRequired": "BYOK 需要 Pro 计划或更高版本。升级以连接您的 API 密钥。",
"byokSettings.title": "您的 API 密钥 (BYOK)",
"chat.timeoutWarning": "响应时间比预期要长...",
"dataManagement.title": "数据",
"generalSettings.title": "一般的",
"labHeader.rename": "重命名",
"landing.pricing.perUser": "+ 3.90 欧元/用户",
"landing.pricing.perUserAnnual": "+ 2.90 欧元/用户,按年计费",
"notebook.generatingDescription": "请稍等...",
"notes.archiveFailed": "存档失败",
"notes.archived": "注释已存档",
"notes.confirmDeleteTitle": "删除注释",
"notes.content": "内容",
"notes.conversionFailed": "转换失败,停留在 Markdown 状态",
"notes.convertedToRichText": "转换为富文本",
"notes.createFailed": "创建笔记失败",
"notes.deleteFailed": "删除笔记失败",
"notes.deleted": "注释已删除",
"notes.dismissed": "最近的注释已被驳回",
"notes.generalNotes": "一般说明",
"notes.historyDisabledTitle": "版本历史",
"notes.historyEnabledDesc": "现在将记录此注释的版本。",
"notes.historyEnabledTitle": "历史记录已启用!",
"notes.leftShare": "分享已删除",
"notes.restore": "恢复",
"notes.sort": "种类",
"notes.suggestTitle": "人工智能标题",
"notes.titleGenerated": "标题已生成",
"notes.updateFailed": "更新笔记失败",
"notification.accept": "接受",
"notification.accepted": "分享已接受",
"notification.decline": "衰退",
"notification.noNotifications": "没有新通知",
"profile.tab": "轮廓",
"richTextEditor.imageUrlPlaceholder": "https://example.com/image.png",
"settings.cardSizeMode": "备注尺寸",
"settings.cardSizeModeDescription": "选择可变尺寸或统一尺寸",
"settings.cardSizeUniform": "尺寸统一",
"settings.cardSizeVariable": "多种尺寸(小/中/大)",
"settings.selectCardSizeMode": "选择显示模式",
"settings.themeBaseGroup": "根据",
"settings.themeBlue": "蓝色的",
"settings.themeGreen": "绿色的",
"settings.themeLavender": "薰衣草",
"settings.themeMidnight": "午夜",
"settings.themeOcean": "海洋",
"settings.themePalettesGroup": "调色板",
"settings.themeSand": "沙",
"settings.themeSepia": "棕褐色",
"settings.themeSunset": "日落",
"sidebar.clearFilter": "移除过滤器",
"sidebar.sharedNotebookBadge": "· 共享",
"sidebar.sortAlpha": "A → Z",
"usageMeter.addApiKey": "使用您自己的 API 密钥 (BYOK)",
"usageMeter.featureBrainstormCreate": "集思广益创作",
"usageMeter.featureBrainstormEnrich": "头脑风暴丰富内容",
"usageMeter.featureBrainstormExpand": "集思广益扩展",
"usageMeter.featureChat": "人工智能消息",
"usageMeter.featureReformulate": "重新配方",
"usageMeter.featureSearch": "搜索",
"usageMeter.featureTags": "标签",
"usageMeter.featureTitles": "标题",
"usageMeter.later": "之后",
"usageMeter.packName": "人工智能探索包",
"usageMeter.proChat": "100 条聊天消息/月",
"usageMeter.proIncludes": "专业版包括:",
"usageMeter.proReformulate": "50 次重新配制/月",
"usageMeter.proSearch": "每月 100 次语义搜索",
"usageMeter.proTags": "200 个自动标签/月",
"usageMeter.proTitles": "每月 200 个自动标题",
"usageMeter.remaining": "还剩 {count} 个",
"usageMeter.unlimited": "无限",
"usageMeter.upgradeDescription": "您已用完所有 AI Discovery Pack 积分。升级到专业版以获得更高的限制和附加功能。",
"usageMeter.upgradePricing": "升级到专业版",
"usageMeter.upgradeTitle": "升级到专业版"
}