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
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:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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 />}
|
||||
|
||||
@@ -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: {
|
||||
|
||||
16
memento-note/app/(main)/template.tsx
Normal file
16
memento-note/app/(main)/template.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
17
memento-note/app/(public)/layout.tsx
Normal file
17
memento-note/app/(public)/layout.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
5
memento-note/app/(public)/page.tsx
Normal file
5
memento-note/app/(public)/page.tsx
Normal file
@@ -0,0 +1,5 @@
|
||||
import { LandingPage } from '@/components/landing-page'
|
||||
|
||||
export default function PublicHomePage() {
|
||||
return <LandingPage />
|
||||
}
|
||||
@@ -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')
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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 }
|
||||
}
|
||||
|
||||
@@ -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, 2–4 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)
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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) {
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -47,7 +47,7 @@ export async function POST(request: NextRequest) {
|
||||
|
||||
await prisma.$transaction(updates)
|
||||
|
||||
revalidatePath('/')
|
||||
revalidatePath('/home')
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
|
||||
@@ -105,7 +105,7 @@ export async function POST(request: NextRequest) {
|
||||
}
|
||||
})
|
||||
|
||||
try { revalidatePath('/') } catch {}
|
||||
try { revalidatePath('/home') } catch {}
|
||||
|
||||
return NextResponse.json({
|
||||
success: true,
|
||||
|
||||
@@ -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).
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -222,7 +222,7 @@ export async function POST(req: NextRequest) {
|
||||
}
|
||||
}
|
||||
|
||||
revalidatePath('/')
|
||||
revalidatePath('/home')
|
||||
revalidatePath('/settings/data')
|
||||
|
||||
return NextResponse.json({ success: true, ...stats })
|
||||
|
||||
@@ -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(
|
||||
|
||||
@@ -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: [] })
|
||||
|
||||
@@ -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 }) {
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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" />}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
)}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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'}
|
||||
|
||||
@@ -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')}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
|
||||
@@ -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')}
|
||||
|
||||
412
memento-note/components/landing-page.tsx
Normal file
412
memento-note/components/landing-page.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
@@ -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}`
|
||||
}}
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -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'}
|
||||
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
@@ -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>
|
||||
)
|
||||
}
|
||||
41
memento-note/components/public-providers.tsx
Normal file
41
memento-note/components/public-providers.tsx
Normal 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>
|
||||
)
|
||||
}
|
||||
@@ -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 {
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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">
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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 |
@@ -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])
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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
|
||||
)
|
||||
|
||||
@@ -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}`
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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[]
|
||||
|
||||
@@ -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);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "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で増幅された第二の脳。クリエイティブな方のために。",
|
||||
"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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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": "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 放大的第二大脑。为创意头脑而设计。",
|
||||
"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": "#"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
BIN
memento-note/public/images/workspace-hero.jpg
Normal file
BIN
memento-note/public/images/workspace-hero.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 355 KiB |
292
memento-note/scripts/apply-missing-i18n.mjs
Normal file
292
memento-note/scripts/apply-missing-i18n.mjs
Normal 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.')
|
||||
145
memento-note/scripts/generate-i18n-overrides.py
Normal file
145
memento-note/scripts/generate-i18n-overrides.py
Normal 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())
|
||||
2615
memento-note/scripts/i18n-landing-patches.json
Normal file
2615
memento-note/scripts/i18n-landing-patches.json
Normal file
File diff suppressed because it is too large
Load Diff
184
memento-note/scripts/i18n-overrides/ar.json
Normal file
184
memento-note/scripts/i18n-overrides/ar.json
Normal 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": "إثراء العصف الذهني"
|
||||
}
|
||||
312
memento-note/scripts/i18n-overrides/de.json
Normal file
312
memento-note/scripts/i18n-overrides/de.json
Normal 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- **3–5 Iterationen:** für einfache Aufgaben (Scraping einer einzelnen Seite)\n- **10 Iterationen (Standard):** guter Kompromiss für die meisten Fälle\n- **15–25 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"
|
||||
}
|
||||
347
memento-note/scripts/i18n-overrides/es.json
Normal file
347
memento-note/scripts/i18n-overrides/es.json
Normal 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"
|
||||
}
|
||||
164
memento-note/scripts/i18n-overrides/fa.json
Normal file
164
memento-note/scripts/i18n-overrides/fa.json
Normal 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 ارتقا دهید"
|
||||
}
|
||||
359
memento-note/scripts/i18n-overrides/generate-overrides.mjs
Normal file
359
memento-note/scripts/i18n-overrides/generate-overrides.mjs
Normal 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)
|
||||
}
|
||||
358
memento-note/scripts/i18n-overrides/hi.json
Normal file
358
memento-note/scripts/i18n-overrides/hi.json
Normal 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": "प्रो में अपग्रेड"
|
||||
}
|
||||
260
memento-note/scripts/i18n-overrides/ja.json
Normal file
260
memento-note/scripts/i18n-overrides/ja.json
Normal 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": "プロにアップグレード"
|
||||
}
|
||||
281
memento-note/scripts/i18n-overrides/ko.json
Normal file
281
memento-note/scripts/i18n-overrides/ko.json
Normal 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": "프로로 업그레이드"
|
||||
}
|
||||
345
memento-note/scripts/i18n-overrides/nl.json
Normal file
345
memento-note/scripts/i18n-overrides/nl.json
Normal 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"
|
||||
}
|
||||
289
memento-note/scripts/i18n-overrides/pl.json
Normal file
289
memento-note/scripts/i18n-overrides/pl.json
Normal 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- **15–25 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"
|
||||
}
|
||||
274
memento-note/scripts/i18n-overrides/ru.json
Normal file
274
memento-note/scripts/i18n-overrides/ru.json
Normal 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- **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> **Совет.** Создайте специальный блокнот, например «Отчеты агента», чтобы централизовать весь автоматизированный контент.",
|
||||
"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": "Мозговой штурм"
|
||||
}
|
||||
259
memento-note/scripts/i18n-overrides/zh.json
Normal file
259
memento-note/scripts/i18n-overrides/zh.json
Normal 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": "升级到专业版"
|
||||
}
|
||||
Reference in New Issue
Block a user