diff --git a/README.es.md b/README.es.md new file mode 100644 index 000000000..86438eded --- /dev/null +++ b/README.es.md @@ -0,0 +1,264 @@ +readme_banner + + + +
+ +Discord + + +Reddit + +
+ +
+ +[English](README.md) | [Español](README.es.md) | [Português](README.pt-BR.md) | [हिन्दी](README.hi.md) | [简体中文](README.zh-CN.md) + +
+ +# SurfSense +Conecta cualquier LLM a tus fuentes de conocimiento internas y chatea con él en tiempo real junto a tu equipo. Alternativa de código abierto a NotebookLM, Perplexity y Glean. + +SurfSense es un agente de investigación de IA altamente personalizable, conectado a fuentes externas como motores de búsqueda (SearxNG, Tavily, LinkUp), Google Drive, Slack, Microsoft Teams, Linear, Jira, ClickUp, Confluence, BookStack, Gmail, Notion, YouTube, GitHub, Discord, Airtable, Google Calendar, Luma, Circleback, Elasticsearch, Obsidian y más por venir. + +
+MODSetter%2FSurfSense | Trendshift +
+ + +# Video + +https://github.com/user-attachments/assets/cc0c84d3-1f2f-4f7a-b519-2ecce22310b1 + + +## Ejemplo de Podcast + +https://github.com/user-attachments/assets/a0a16566-6967-4374-ac51-9b3e07fbecd7 + + + + +## Funcionalidades Principales + +### 💡 **Idea**: +- Alternativa de código abierto a NotebookLM, Perplexity y Glean. Conecta cualquier LLM a tus fuentes de conocimiento internas y colabora con tu equipo en tiempo real. +### 📁 **Soporte de Múltiples Formatos de Archivo** +- Guarda contenido de tus archivos personales *(Documentos, imágenes, videos y soporta **más de 50 extensiones de archivo**)* en tu propia base de conocimiento personal. +### 🔍 **Búsqueda Potente** +- Investiga o encuentra rápidamente cualquier cosa en tu contenido guardado. +### 💬 **Chatea con tu Contenido Guardado** +- Interactúa en lenguaje natural y obtén respuestas con citas. +### 📄 **Respuestas con Citas** +- Obtén respuestas con citas como en Perplexity. +### 🧩 **Compatibilidad Universal** +- Conecta virtualmente cualquier proveedor de inferencia a través de la especificación OpenAI y LiteLLM. +### 🔔 **Privacidad y Soporte de LLM Local** +- Funciona perfectamente con LLMs locales como vLLM y Ollama. +### 🏠 **Auto-Hospedable** +- Código abierto y fácil de desplegar localmente. +### 👥 **Colaboración en Equipo con RBAC** +- Control de acceso basado en roles para los espacios de búsqueda +- Invita a miembros del equipo con roles personalizables (Propietario, Admin, Editor, Visor) +- Permisos granulares para documentos, chats, conectores y configuración +- Comparte bases de conocimiento de forma segura dentro de tu organización +- Los chats de equipo se actualizan en tiempo real y puedes "Chatear sobre el chat" en hilos de comentarios +### 🎙️ Podcasts +- Agente de generación de podcasts ultrarrápido. (Crea un podcast de 3 minutos en menos de 20 segundos.) +- Convierte tus conversaciones de chat en contenido de audio atractivo +- Soporte para proveedores TTS locales (Kokoro TTS) +- Soporte para múltiples proveedores TTS (OpenAI, Azure, Google Vertex AI) + +### 🤖 **Arquitectura de Agentes Profundos** +- Impulsado por [LangChain Deep Agents](https://docs.langchain.com/oss/python/deepagents/overview) - agentes que pueden planificar, usar subagentes y aprovechar sistemas de archivos para tareas complejas. + +### 📊 **Técnicas Avanzadas de RAG** +- Soporta más de 100 LLMs +- Soporta más de 6000 modelos de embeddings +- Soporta todos los principales rerankers (Pinecone, Cohere, Flashrank, etc.) +- Utiliza índices jerárquicos (configuración RAG de 2 niveles) +- Utiliza búsqueda híbrida (Semántica + Texto completo combinado con Reciprocal Rank Fusion) + +### ℹ️ **Fuentes Externas** +- Motores de búsqueda (Tavily, LinkUp) +- SearxNG (instancias auto-hospedadas) +- Google Drive +- Slack +- Microsoft Teams +- Linear +- Jira +- ClickUp +- Confluence +- BookStack +- Notion +- Gmail +- Videos de YouTube +- GitHub +- Discord +- Airtable +- Google Calendar +- Luma +- Circleback +- Elasticsearch +- Obsidian +- y más por venir..... + +## 📄 **Extensiones de Archivo Soportadas** + +| Servicio ETL | Formatos | Notas | +|--------------|----------|-------| +| **LlamaCloud** | 50+ formatos | Documentos, presentaciones, hojas de cálculo, imágenes | +| **Unstructured** | 34+ formatos | Formatos principales + soporte de email | +| **Docling** | Formatos principales | Procesamiento local, no requiere clave API | + +**Audio/Video** (vía servicio STT): `.mp3`, `.wav`, `.mp4`, `.webm`, etc. + +### 🔖 Extensión Multi-Navegador +- La extensión de SurfSense se puede usar para guardar cualquier página web que desees. +- Su principal uso es guardar páginas web protegidas por autenticación. + + + +## SOLICITUDES DE FUNCIONES Y FUTURO + + +**SurfSense está en desarrollo activo.** Aunque aún no está listo para producción, puedes ayudarnos a acelerar el proceso. + +¡Únete al [Discord de SurfSense](https://discord.gg/ejRNvftDp9) y ayuda a dar forma al futuro de SurfSense! + +## 🚀 Hoja de Ruta + +¡Mantente al día con nuestro progreso de desarrollo y próximas funcionalidades! +Consulta nuestra hoja de ruta pública y contribuye con tus ideas o comentarios: + +**📋 Discusión de la Hoja de Ruta:** [SurfSense 2025-2026 Roadmap: Deep Agents, Real-Time Collaboration & MCP Servers](https://github.com/MODSetter/SurfSense/discussions/565) + +**📊 Tablero Kanban:** [SurfSense Project Board](https://github.com/users/MODSetter/projects/3) + + +## ¿Cómo empezar? + +### Inicio Rápido con Docker 🐳 + +> [!TIP] +> Para despliegues en producción, usa la configuración completa de [Docker Compose](https://www.surfsense.com/docs/docker-installation) que ofrece más control y escalabilidad. + +**Linux/macOS:** + +```bash +docker run -d -p 3000:3000 -p 8000:8000 -p 5133:5133 \ + -v surfsense-data:/data \ + --name surfsense \ + --restart unless-stopped \ + ghcr.io/modsetter/surfsense:latest +``` + +**Windows (PowerShell):** + +```powershell +docker run -d -p 3000:3000 -p 8000:8000 -p 5133:5133 ` + -v surfsense-data:/data ` + --name surfsense ` + --restart unless-stopped ` + ghcr.io/modsetter/surfsense:latest +``` + +**Con Configuración Personalizada:** + +Puedes pasar cualquier variable de entorno usando flags `-e`: + +```bash +docker run -d -p 3000:3000 -p 8000:8000 -p 5133:5133 \ + -v surfsense-data:/data \ + -e EMBEDDING_MODEL=openai://text-embedding-ada-002 \ + -e OPENAI_API_KEY=your_openai_api_key \ + -e AUTH_TYPE=GOOGLE \ + -e GOOGLE_OAUTH_CLIENT_ID=your_google_client_id \ + -e GOOGLE_OAUTH_CLIENT_SECRET=your_google_client_secret \ + -e ETL_SERVICE=LLAMACLOUD \ + -e LLAMA_CLOUD_API_KEY=your_llama_cloud_key \ + --name surfsense \ + --restart unless-stopped \ + ghcr.io/modsetter/surfsense:latest +``` + +> [!NOTE] +> - Si despliegas detrás de un proxy inverso con HTTPS, agrega `-e BACKEND_URL=https://api.yourdomain.com` + +Después de iniciar, accede a SurfSense en: +- **Frontend**: [http://localhost:3000](http://localhost:3000) +- **API Backend**: [http://localhost:8000](http://localhost:8000) +- **Documentación API**: [http://localhost:8000/docs](http://localhost:8000/docs) +- **Electric-SQL**: [http://localhost:5133](http://localhost:5133) + +**Comandos Útiles:** + +```bash +docker logs -f surfsense # Ver logs +docker stop surfsense # Detener +docker start surfsense # Iniciar +docker rm surfsense # Eliminar (datos preservados en el volumen) +``` + +### Opciones de Instalación + +SurfSense ofrece múltiples opciones para empezar: + +1. **[SurfSense Cloud](https://www.surfsense.com/login)** - La forma más fácil de probar SurfSense sin ninguna configuración. + - No requiere instalación + - Acceso instantáneo a todas las funcionalidades + - Perfecto para empezar rápidamente + +2. **Inicio Rápido Docker (Arriba)** - Un solo comando para tener SurfSense funcionando localmente. + - Imagen todo-en-uno con PostgreSQL, Redis y todos los servicios incluidos + - Perfecto para evaluación, desarrollo y despliegues pequeños + - Datos persistidos vía volumen Docker + +3. **[Docker Compose (Producción)](https://www.surfsense.com/docs/docker-installation)** - Despliegue de stack completo con servicios separados. + - Incluye pgAdmin para gestión de base de datos a través de interfaz web + - Soporta personalización de variables de entorno vía archivo `.env` + - Opciones de despliegue flexibles (stack completo o solo servicios principales) + - Mejor para producción con escalado independiente de servicios + +4. **[Instalación Manual](https://www.surfsense.com/docs/manual-installation)** - Para usuarios que prefieren más control sobre su configuración o necesitan personalizar su despliegue. + +Las guías de Docker e instalación manual incluyen instrucciones detalladas específicas para Windows, macOS y Linux. + +Antes de la instalación auto-hospedada, asegúrate de completar los [pasos de configuración previos](https://www.surfsense.com/docs/) incluyendo: +- Configuración de autenticación (opcional - por defecto usa autenticación LOCAL) +- **Servicio ETL de Procesamiento de Archivos** (opcional - por defecto usa Docling): + - Docling (por defecto, procesamiento local, no requiere clave API, soporta PDF, documentos Office, imágenes, HTML, CSV) + - Clave API de Unstructured.io (soporta 34+ formatos) + - Clave API de LlamaIndex (análisis mejorado, soporta 50+ formatos) +- Otras claves API según sea necesario para tu caso de uso + + +## Contribuir + +¡Las contribuciones son muy bienvenidas! Una contribución puede ser tan pequeña como una ⭐ o incluso encontrar y crear issues. +El ajuste fino del Backend siempre es deseado. + +Para guías detalladas de contribución, consulta nuestro archivo [CONTRIBUTING.md](CONTRIBUTING.md). + +## Historial de Stars + + + + + + Star History Chart + + + +--- +--- +

+ Catalyst Project +

+ +--- +--- diff --git a/README.hi.md b/README.hi.md new file mode 100644 index 000000000..6ba70097d --- /dev/null +++ b/README.hi.md @@ -0,0 +1,264 @@ +readme_banner + + + +
+ +Discord + + +Reddit + +
+ +
+ +[English](README.md) | [Español](README.es.md) | [Português](README.pt-BR.md) | [हिन्दी](README.hi.md) | [简体中文](README.zh-CN.md) + +
+ +# SurfSense +किसी भी LLM को अपने आंतरिक ज्ञान स्रोतों से जोड़ें और अपनी टीम के साथ रीयल-टाइम में चैट करें। NotebookLM, Perplexity और Glean का ओपन सोर्स विकल्प। + +SurfSense एक अत्यधिक अनुकूलन योग्य AI शोध एजेंट है, जो बाहरी स्रोतों से जुड़ा है जैसे सर्च इंजन (SearxNG, Tavily, LinkUp), Google Drive, Slack, Microsoft Teams, Linear, Jira, ClickUp, Confluence, BookStack, Gmail, Notion, YouTube, GitHub, Discord, Airtable, Google Calendar, Luma, Circleback, Elasticsearch, Obsidian और भी बहुत कुछ आने वाला है। + +
+MODSetter%2FSurfSense | Trendshift +
+ + +# वीडियो + +https://github.com/user-attachments/assets/cc0c84d3-1f2f-4f7a-b519-2ecce22310b1 + + +## पॉडकास्ट नमूना + +https://github.com/user-attachments/assets/a0a16566-6967-4374-ac51-9b3e07fbecd7 + + + + +## प्रमुख विशेषताएं + +### 💡 **विचार**: +- NotebookLM, Perplexity और Glean का ओपन सोर्स विकल्प। किसी भी LLM को अपने आंतरिक ज्ञान स्रोतों से जोड़ें और अपनी टीम के साथ रीयल-टाइम में सहयोग करें। +### 📁 **कई फ़ाइल फ़ॉर्मेट अपलोड सपोर्ट** +- अपनी व्यक्तिगत फ़ाइलों *(दस्तावेज़, चित्र, वीडियो और **50+ फ़ाइल एक्सटेंशन** का समर्थन)* से सामग्री को अपने व्यक्तिगत ज्ञान आधार में सहेजें। +### 🔍 **शक्तिशाली खोज** +- अपनी सहेजी गई सामग्री में कुछ भी तुरंत खोजें या शोध करें। +### 💬 **अपनी सहेजी गई सामग्री के साथ चैट करें** +- प्राकृतिक भाषा में बातचीत करें और उद्धृत उत्तर प्राप्त करें। +### 📄 **उद्धृत उत्तर** +- Perplexity की तरह उद्धृत उत्तर प्राप्त करें। +### 🧩 **सार्वभौमिक अनुकूलता** +- OpenAI स्पेक और LiteLLM के माध्यम से लगभग किसी भी इंफ्रेंस प्रदाता को कनेक्ट करें। +### 🔔 **गोपनीयता और स्थानीय LLM सपोर्ट** +- vLLM और Ollama जैसे स्थानीय LLMs के साथ बेहतरीन काम करता है। +### 🏠 **सेल्फ-होस्ट करने योग्य** +- ओपन सोर्स और स्थानीय रूप से तैनात करना आसान। +### 👥 **RBAC के साथ टीम सहयोग** +- सर्च स्पेस के लिए भूमिका-आधारित एक्सेस नियंत्रण +- अनुकूलन योग्य भूमिकाओं (मालिक, एडमिन, संपादक, दर्शक) के साथ टीम सदस्यों को आमंत्रित करें +- दस्तावेज़ों, चैट, कनेक्टर और सेटिंग्स के लिए विस्तृत अनुमतियां +- अपने संगठन के भीतर सुरक्षित रूप से ज्ञान आधार साझा करें +- टीम चैट रीयल-टाइम में अपडेट होते हैं और कमेंट थ्रेड में "चैट के बारे में चैट" करें +### 🎙️ पॉडकास्ट +- अत्यंत तेज़ पॉडकास्ट जनरेशन एजेंट। (20 सेकंड से कम में 3 मिनट का पॉडकास्ट बनाता है।) +- अपनी चैट बातचीत को आकर्षक ऑडियो सामग्री में बदलें +- स्थानीय TTS प्रदाताओं का समर्थन (Kokoro TTS) +- कई TTS प्रदाताओं का समर्थन (OpenAI, Azure, Google Vertex AI) + +### 🤖 **डीप एजेंट आर्किटेक्चर** +- [LangChain Deep Agents](https://docs.langchain.com/oss/python/deepagents/overview) द्वारा संचालित - ऐसे एजेंट जो योजना बना सकते हैं, सब-एजेंट का उपयोग कर सकते हैं, और जटिल कार्यों के लिए फ़ाइल सिस्टम का लाभ उठा सकते हैं। + +### 📊 **उन्नत RAG तकनीकें** +- 100+ LLMs का समर्थन +- 6000+ एम्बेडिंग मॉडल का समर्थन +- सभी प्रमुख रीरैंकर्स का समर्थन (Pinecone, Cohere, Flashrank आदि) +- हायरार्किकल इंडाइसेस का उपयोग (2 स्तरीय RAG सेटअप) +- हाइब्रिड सर्च का उपयोग (सिमैंटिक + फुल टेक्स्ट सर्च, Reciprocal Rank Fusion के साथ) + +### ℹ️ **बाहरी स्रोत** +- सर्च इंजन (Tavily, LinkUp) +- SearxNG (सेल्फ-होस्टेड इंस्टेंस) +- Google Drive +- Slack +- Microsoft Teams +- Linear +- Jira +- ClickUp +- Confluence +- BookStack +- Notion +- Gmail +- YouTube वीडियो +- GitHub +- Discord +- Airtable +- Google Calendar +- Luma +- Circleback +- Elasticsearch +- Obsidian +- और भी बहुत कुछ आने वाला है..... + +## 📄 **समर्थित फ़ाइल एक्सटेंशन** + +| ETL सेवा | फ़ॉर्मेट | नोट्स | +|-----------|----------|-------| +| **LlamaCloud** | 50+ फ़ॉर्मेट | दस्तावेज़, प्रस्तुतियां, स्प्रेडशीट, चित्र | +| **Unstructured** | 34+ फ़ॉर्मेट | मुख्य फ़ॉर्मेट + ईमेल समर्थन | +| **Docling** | मुख्य फ़ॉर्मेट | स्थानीय प्रोसेसिंग, API कुंजी की आवश्यकता नहीं | + +**ऑडियो/वीडियो** (STT सेवा के माध्यम से): `.mp3`, `.wav`, `.mp4`, `.webm`, आदि। + +### 🔖 क्रॉस-ब्राउज़र एक्सटेंशन +- SurfSense एक्सटेंशन का उपयोग किसी भी वेबपेज को सहेजने के लिए किया जा सकता है। +- इसका मुख्य उपयोग प्रमाणीकरण द्वारा संरक्षित वेबपेजों को सहेजना है। + + + +## फ़ीचर अनुरोध और भविष्य + + +**SurfSense सक्रिय रूप से विकसित किया जा रहा है।** हालांकि यह अभी प्रोडक्शन-रेडी नहीं है, आप प्रक्रिया को तेज़ करने में हमारी मदद कर सकते हैं। + +[SurfSense Discord](https://discord.gg/ejRNvftDp9) में शामिल हों और SurfSense के भविष्य को आकार देने में मदद करें! + +## 🚀 रोडमैप + +हमारे विकास की प्रगति और आने वाली सुविधाओं से अपडेट रहें! +हमारा सार्वजनिक रोडमैप देखें और अपने विचार या फ़ीडबैक दें: + +**📋 रोडमैप चर्चा:** [SurfSense 2025-2026 Roadmap: Deep Agents, Real-Time Collaboration & MCP Servers](https://github.com/MODSetter/SurfSense/discussions/565) + +**📊 कानबन बोर्ड:** [SurfSense Project Board](https://github.com/users/MODSetter/projects/3) + + +## कैसे शुरू करें? + +### Docker के साथ त्वरित शुरुआत 🐳 + +> [!TIP] +> प्रोडक्शन डिप्लॉयमेंट के लिए, पूर्ण [Docker Compose सेटअप](https://www.surfsense.com/docs/docker-installation) का उपयोग करें जो अधिक नियंत्रण और स्केलेबिलिटी प्रदान करता है। + +**Linux/macOS:** + +```bash +docker run -d -p 3000:3000 -p 8000:8000 -p 5133:5133 \ + -v surfsense-data:/data \ + --name surfsense \ + --restart unless-stopped \ + ghcr.io/modsetter/surfsense:latest +``` + +**Windows (PowerShell):** + +```powershell +docker run -d -p 3000:3000 -p 8000:8000 -p 5133:5133 ` + -v surfsense-data:/data ` + --name surfsense ` + --restart unless-stopped ` + ghcr.io/modsetter/surfsense:latest +``` + +**कस्टम कॉन्फ़िगरेशन के साथ:** + +आप `-e` फ़्लैग का उपयोग करके कोई भी एन्वायरनमेंट वेरिएबल पास कर सकते हैं: + +```bash +docker run -d -p 3000:3000 -p 8000:8000 -p 5133:5133 \ + -v surfsense-data:/data \ + -e EMBEDDING_MODEL=openai://text-embedding-ada-002 \ + -e OPENAI_API_KEY=your_openai_api_key \ + -e AUTH_TYPE=GOOGLE \ + -e GOOGLE_OAUTH_CLIENT_ID=your_google_client_id \ + -e GOOGLE_OAUTH_CLIENT_SECRET=your_google_client_secret \ + -e ETL_SERVICE=LLAMACLOUD \ + -e LLAMA_CLOUD_API_KEY=your_llama_cloud_key \ + --name surfsense \ + --restart unless-stopped \ + ghcr.io/modsetter/surfsense:latest +``` + +> [!NOTE] +> - यदि HTTPS के साथ रिवर्स प्रॉक्सी के पीछे डिप्लॉय कर रहे हैं, तो `-e BACKEND_URL=https://api.yourdomain.com` जोड़ें + +शुरू करने के बाद, SurfSense तक पहुंचें: +- **फ्रंटएंड**: [http://localhost:3000](http://localhost:3000) +- **बैकएंड API**: [http://localhost:8000](http://localhost:8000) +- **API डॉक्स**: [http://localhost:8000/docs](http://localhost:8000/docs) +- **Electric-SQL**: [http://localhost:5133](http://localhost:5133) + +**उपयोगी कमांड:** + +```bash +docker logs -f surfsense # लॉग देखें +docker stop surfsense # रोकें +docker start surfsense # शुरू करें +docker rm surfsense # हटाएं (डेटा वॉल्यूम में सुरक्षित रहता है) +``` + +### इंस्टॉलेशन विकल्प + +SurfSense शुरू करने के लिए कई विकल्प प्रदान करता है: + +1. **[SurfSense Cloud](https://www.surfsense.com/login)** - बिना किसी सेटअप के SurfSense आज़माने का सबसे आसान तरीका। + - इंस्टॉलेशन की आवश्यकता नहीं + - सभी सुविधाओं तक तत्काल पहुंच + - जल्दी शुरू करने के लिए बिल्कुल सही + +2. **Docker त्वरित शुरुआत (ऊपर)** - एक ही कमांड से SurfSense को स्थानीय रूप से चलाएं। + - PostgreSQL, Redis और सभी सेवाओं के साथ ऑल-इन-वन इमेज + - मूल्यांकन, विकास और छोटे डिप्लॉयमेंट के लिए बिल्कुल सही + - Docker वॉल्यूम के माध्यम से डेटा पर्सिस्ट + +3. **[Docker Compose (प्रोडक्शन)](https://www.surfsense.com/docs/docker-installation)** - अलग-अलग सेवाओं के साथ पूर्ण स्टैक डिप्लॉयमेंट। + - वेब UI के माध्यम से डेटाबेस प्रबंधन के लिए pgAdmin शामिल + - `.env` फ़ाइल के माध्यम से एन्वायरनमेंट वेरिएबल कस्टमाइज़ेशन का समर्थन + - लचीले डिप्लॉयमेंट विकल्प (पूर्ण स्टैक या केवल मुख्य सेवाएं) + - सेवाओं के स्वतंत्र स्केलिंग के साथ प्रोडक्शन के लिए बेहतर + +4. **[मैनुअल इंस्टॉलेशन](https://www.surfsense.com/docs/manual-installation)** - उन उपयोगकर्ताओं के लिए जो अपने सेटअप पर अधिक नियंत्रण चाहते हैं या अपने डिप्लॉयमेंट को कस्टमाइज़ करना चाहते हैं। + +Docker और मैनुअल इंस्टॉलेशन गाइड में Windows, macOS और Linux के लिए विस्तृत OS-विशिष्ट निर्देश शामिल हैं। + +सेल्फ-होस्टिंग इंस्टॉलेशन से पहले, [पूर्वापेक्षा सेटअप चरण](https://www.surfsense.com/docs/) पूरा करना सुनिश्चित करें, जिसमें शामिल हैं: +- प्रमाणीकरण सेटअप (वैकल्पिक - डिफ़ॉल्ट LOCAL प्रमाणीकरण) +- **फ़ाइल प्रोसेसिंग ETL सेवा** (वैकल्पिक - डिफ़ॉल्ट Docling): + - Docling (डिफ़ॉल्ट, स्थानीय प्रोसेसिंग, API कुंजी की आवश्यकता नहीं, PDF, Office दस्तावेज़, चित्र, HTML, CSV का समर्थन) + - Unstructured.io API कुंजी (34+ फ़ॉर्मेट का समर्थन) + - LlamaIndex API कुंजी (उन्नत पार्सिंग, 50+ फ़ॉर्मेट का समर्थन) +- आपके उपयोग के अनुसार अन्य API कुंजियां + + +## योगदान करें + +योगदान का बहुत स्वागत है! योगदान एक ⭐ जितना छोटा हो सकता है या issues खोजना और बनाना भी। +बैकएंड की फ़ाइन-ट्यूनिंग हमेशा वांछित है। + +विस्तृत योगदान दिशानिर्देशों के लिए, कृपया हमारी [CONTRIBUTING.md](CONTRIBUTING.md) फ़ाइल देखें। + +## Star इतिहास + + + + + + Star History Chart + + + +--- +--- +

+ Catalyst Project +

+ +--- +--- diff --git a/README.md b/README.md index 4dd368c04..3fb8014c5 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@
-[English](README.md) | [简体中文](README.zh-CN.md) +[English](README.md) | [Español](README.es.md) | [Português](README.pt-BR.md) | [हिन्दी](README.hi.md) | [简体中文](README.zh-CN.md)
@@ -233,103 +233,11 @@ Before self-hosting installation, make sure to complete the [prerequisite setup - Other API keys as needed for your use case - -## Tech Stack - - - ### **BackEnd** - -- **LiteLLM**: Universal LLM integration supporting 100+ models (OpenAI, Anthropic, Ollama, etc.) - -- **FastAPI**: Modern, fast web framework for building APIs with Python - -- **PostgreSQL with pgvector**: Database with vector search capabilities for similarity searches - -- **SQLAlchemy**: SQL toolkit and ORM (Object-Relational Mapping) for database interactions - -- **Alembic**: A database migrations tool for SQLAlchemy. - -- **FastAPI Users**: Authentication and user management with JWT and OAuth support - -- **Deep Agents**: Custom agent framework built on LangGraph for reasoning and acting AI agents with configurable tools - -- **LangGraph**: Framework for developing stateful AI agents with conversation persistence - -- **LangChain**: Framework for developing AI-powered applications. - -- **Rerankers**: Advanced result ranking for improved search relevance - -- **Hybrid Search**: Combines vector similarity and full-text search for optimal results using Reciprocal Rank Fusion (RRF) - -- **Vector Embeddings**: Document and text embeddings for semantic search - -- **pgvector**: PostgreSQL extension for efficient vector similarity operations - -- **Redis**: In-memory data structure store used as message broker and result backend for Celery - -- **Celery**: Distributed task queue for handling asynchronous background jobs (document processing, podcast generation, etc.) - -- **Flower**: Real-time monitoring and administration tool for Celery task queues - -- **Chonkie**: Advanced document chunking and embedding library - - ---- - ### **FrontEnd** - -- **Next.js**: React framework featuring App Router, server components, automatic code-splitting, and optimized rendering. - -- **React**: JavaScript library for building user interfaces. - -- **TypeScript**: Static type-checking for JavaScript, enhancing code quality and developer experience. - -- **Vercel AI SDK Kit UI Stream Protocol**: To create scalable chat UI. - -- **Tailwind CSS**: Utility-first CSS framework for building custom UI designs. - -- **Shadcn**: Headless components library. - -- **Motion (Framer Motion)**: Animation library for React. - - - - ### **DevOps** - -- **Docker**: Container platform for consistent deployment across environments - -- **Docker Compose**: Tool for defining and running multi-container Docker applications - -- **pgAdmin**: Web-based PostgreSQL administration tool included in Docker setup - - -### **Extension** - Manifest v3 on Plasmo - - ## Contribute Contributions are very welcome! A contribution can be as small as a ⭐ or even finding and creating issues. Fine-tuning the Backend is always desired. -### Adding New Agent Tools - -Want to add a new tool to the SurfSense agent? It's easy: - -1. Create your tool file in `surfsense_backend/app/agents/new_chat/tools/my_tool.py` -2. Register it in `registry.py`: - -```python -ToolDefinition( - name="my_tool", - description="What my tool does", - factory=lambda deps: create_my_tool( - search_space_id=deps["search_space_id"], - db_session=deps["db_session"], - ), - requires=["search_space_id", "db_session"], -), -``` - For detailed contribution guidelines, please see our [CONTRIBUTING.md](CONTRIBUTING.md) file. ## Star History diff --git a/README.pt-BR.md b/README.pt-BR.md new file mode 100644 index 000000000..f57c28664 --- /dev/null +++ b/README.pt-BR.md @@ -0,0 +1,264 @@ +readme_banner + + + +
+ +Discord + + +Reddit + +
+ +
+ +[English](README.md) | [Español](README.es.md) | [Português](README.pt-BR.md) | [हिन्दी](README.hi.md) | [简体中文](README.zh-CN.md) + +
+ +# SurfSense +Conecte qualquer LLM às suas fontes de conhecimento internas e converse com ele em tempo real junto com sua equipe. Alternativa de código aberto ao NotebookLM, Perplexity e Glean. + +SurfSense é um agente de pesquisa de IA altamente personalizável, conectado a fontes externas como mecanismos de busca (SearxNG, Tavily, LinkUp), Google Drive, Slack, Microsoft Teams, Linear, Jira, ClickUp, Confluence, BookStack, Gmail, Notion, YouTube, GitHub, Discord, Airtable, Google Calendar, Luma, Circleback, Elasticsearch, Obsidian e mais por vir. + +
+MODSetter%2FSurfSense | Trendshift +
+ + +# Vídeo + +https://github.com/user-attachments/assets/cc0c84d3-1f2f-4f7a-b519-2ecce22310b1 + + +## Exemplo de Podcast + +https://github.com/user-attachments/assets/a0a16566-6967-4374-ac51-9b3e07fbecd7 + + + + +## Funcionalidades Principais + +### 💡 **Ideia**: +- Alternativa de código aberto ao NotebookLM, Perplexity e Glean. Conecte qualquer LLM às suas fontes de conhecimento internas e colabore com sua equipe em tempo real. +### 📁 **Suporte a Múltiplos Formatos de Arquivo** +- Salve conteúdo dos seus arquivos pessoais *(Documentos, imagens, vídeos e suporta **mais de 50 extensões de arquivo**)* na sua própria base de conhecimento pessoal. +### 🔍 **Pesquisa Poderosa** +- Pesquise ou encontre rapidamente qualquer coisa no seu conteúdo salvo. +### 💬 **Converse com seu Conteúdo Salvo** +- Interaja em linguagem natural e obtenha respostas com citações. +### 📄 **Respostas com Citações** +- Obtenha respostas com citações como no Perplexity. +### 🧩 **Compatibilidade Universal** +- Conecte virtualmente qualquer provedor de inferência via especificação OpenAI e LiteLLM. +### 🔔 **Privacidade e Suporte a LLM Local** +- Funciona perfeitamente com LLMs locais como vLLM e Ollama. +### 🏠 **Auto-Hospedável** +- Código aberto e fácil de implantar localmente. +### 👥 **Colaboração em Equipe com RBAC** +- Controle de acesso baseado em funções para Espaços de Pesquisa +- Convide membros da equipe com funções personalizáveis (Proprietário, Admin, Editor, Visualizador) +- Permissões granulares para documentos, chats, conectores e configurações +- Compartilhe bases de conhecimento com segurança dentro da sua organização +- Chats de equipe atualizam em tempo real e "Converse sobre o chat" em threads de comentários +### 🎙️ Podcasts +- Agente de geração de podcasts ultrarrápido. (Cria um podcast de 3 minutos em menos de 20 segundos.) +- Converta suas conversas de chat em conteúdo de áudio envolvente +- Suporte para provedores TTS locais (Kokoro TTS) +- Suporte para múltiplos provedores TTS (OpenAI, Azure, Google Vertex AI) + +### 🤖 **Arquitetura de Agentes Profundos** +- Alimentado por [LangChain Deep Agents](https://docs.langchain.com/oss/python/deepagents/overview) - agentes que podem planejar, usar subagentes e aproveitar sistemas de arquivos para tarefas complexas. + +### 📊 **Técnicas Avançadas de RAG** +- Suporta mais de 100 LLMs +- Suporta mais de 6000 modelos de embeddings +- Suporta todos os principais rerankers (Pinecone, Cohere, Flashrank, etc.) +- Utiliza índices hierárquicos (configuração RAG de 2 níveis) +- Utiliza busca híbrida (Semântica + Texto completo combinado com Reciprocal Rank Fusion) + +### ℹ️ **Fontes Externas** +- Mecanismos de busca (Tavily, LinkUp) +- SearxNG (instâncias auto-hospedadas) +- Google Drive +- Slack +- Microsoft Teams +- Linear +- Jira +- ClickUp +- Confluence +- BookStack +- Notion +- Gmail +- Vídeos do YouTube +- GitHub +- Discord +- Airtable +- Google Calendar +- Luma +- Circleback +- Elasticsearch +- Obsidian +- e mais por vir..... + +## 📄 **Extensões de Arquivo Suportadas** + +| Serviço ETL | Formatos | Notas | +|-------------|----------|-------| +| **LlamaCloud** | 50+ formatos | Documentos, apresentações, planilhas, imagens | +| **Unstructured** | 34+ formatos | Formatos principais + suporte a e-mail | +| **Docling** | Formatos principais | Processamento local, sem necessidade de chave API | + +**Áudio/Vídeo** (via serviço STT): `.mp3`, `.wav`, `.mp4`, `.webm`, etc. + +### 🔖 Extensão Multi-Navegador +- A extensão do SurfSense pode ser usada para salvar qualquer página web que você desejar. +- Seu principal uso é salvar páginas web protegidas por autenticação. + + + +## SOLICITAÇÕES DE FUNCIONALIDADES E FUTURO + + +**O SurfSense está em desenvolvimento ativo.** Embora ainda não esteja pronto para produção, você pode nos ajudar a acelerar o processo. + +Junte-se ao [Discord do SurfSense](https://discord.gg/ejRNvftDp9) e ajude a moldar o futuro do SurfSense! + +## 🚀 Roadmap + +Fique atualizado com nosso progresso de desenvolvimento e próximas funcionalidades! +Confira nosso roadmap público e contribua com suas ideias ou feedback: + +**📋 Discussão do Roadmap:** [SurfSense 2025-2026 Roadmap: Deep Agents, Real-Time Collaboration & MCP Servers](https://github.com/MODSetter/SurfSense/discussions/565) + +**📊 Quadro Kanban:** [SurfSense Project Board](https://github.com/users/MODSetter/projects/3) + + +## Como começar? + +### Início Rápido com Docker 🐳 + +> [!TIP] +> Para implantações em produção, use a configuração completa do [Docker Compose](https://www.surfsense.com/docs/docker-installation) que oferece mais controle e escalabilidade. + +**Linux/macOS:** + +```bash +docker run -d -p 3000:3000 -p 8000:8000 -p 5133:5133 \ + -v surfsense-data:/data \ + --name surfsense \ + --restart unless-stopped \ + ghcr.io/modsetter/surfsense:latest +``` + +**Windows (PowerShell):** + +```powershell +docker run -d -p 3000:3000 -p 8000:8000 -p 5133:5133 ` + -v surfsense-data:/data ` + --name surfsense ` + --restart unless-stopped ` + ghcr.io/modsetter/surfsense:latest +``` + +**Com Configuração Personalizada:** + +Você pode passar qualquer variável de ambiente usando flags `-e`: + +```bash +docker run -d -p 3000:3000 -p 8000:8000 -p 5133:5133 \ + -v surfsense-data:/data \ + -e EMBEDDING_MODEL=openai://text-embedding-ada-002 \ + -e OPENAI_API_KEY=your_openai_api_key \ + -e AUTH_TYPE=GOOGLE \ + -e GOOGLE_OAUTH_CLIENT_ID=your_google_client_id \ + -e GOOGLE_OAUTH_CLIENT_SECRET=your_google_client_secret \ + -e ETL_SERVICE=LLAMACLOUD \ + -e LLAMA_CLOUD_API_KEY=your_llama_cloud_key \ + --name surfsense \ + --restart unless-stopped \ + ghcr.io/modsetter/surfsense:latest +``` + +> [!NOTE] +> - Se estiver implantando atrás de um proxy reverso com HTTPS, adicione `-e BACKEND_URL=https://api.yourdomain.com` + +Após iniciar, acesse o SurfSense em: +- **Frontend**: [http://localhost:3000](http://localhost:3000) +- **API Backend**: [http://localhost:8000](http://localhost:8000) +- **Documentação da API**: [http://localhost:8000/docs](http://localhost:8000/docs) +- **Electric-SQL**: [http://localhost:5133](http://localhost:5133) + +**Comandos Úteis:** + +```bash +docker logs -f surfsense # Ver logs +docker stop surfsense # Parar +docker start surfsense # Iniciar +docker rm surfsense # Remover (dados preservados no volume) +``` + +### Opções de Instalação + +O SurfSense oferece múltiplas opções para começar: + +1. **[SurfSense Cloud](https://www.surfsense.com/login)** - A forma mais fácil de experimentar o SurfSense sem nenhuma configuração. + - Sem necessidade de instalação + - Acesso instantâneo a todas as funcionalidades + - Perfeito para começar rapidamente + +2. **Início Rápido Docker (Acima)** - Um único comando para ter o SurfSense rodando localmente. + - Imagem tudo-em-um com PostgreSQL, Redis e todos os serviços incluídos + - Perfeito para avaliação, desenvolvimento e implantações pequenas + - Dados persistidos via volume Docker + +3. **[Docker Compose (Produção)](https://www.surfsense.com/docs/docker-installation)** - Implantação de stack completo com serviços separados. + - Inclui pgAdmin para gerenciamento de banco de dados via interface web + - Suporta personalização de variáveis de ambiente via arquivo `.env` + - Opções de implantação flexíveis (stack completo ou apenas serviços principais) + - Melhor para produção com escalamento independente de serviços + +4. **[Instalação Manual](https://www.surfsense.com/docs/manual-installation)** - Para usuários que preferem mais controle sobre sua configuração ou precisam personalizar sua implantação. + +Os guias de Docker e instalação manual incluem instruções detalhadas específicas para Windows, macOS e Linux. + +Antes da instalação auto-hospedada, certifique-se de completar os [passos de configuração prévia](https://www.surfsense.com/docs/) incluindo: +- Configuração de autenticação (opcional - padrão é autenticação LOCAL) +- **Serviço ETL de Processamento de Arquivos** (opcional - padrão é Docling): + - Docling (padrão, processamento local, sem necessidade de chave API, suporta PDF, documentos Office, imagens, HTML, CSV) + - Chave API do Unstructured.io (suporta 34+ formatos) + - Chave API do LlamaIndex (análise aprimorada, suporta 50+ formatos) +- Outras chaves API conforme necessário para seu caso de uso + + +## Contribuir + +Contribuições são muito bem-vindas! Uma contribuição pode ser tão pequena quanto uma ⭐ ou até mesmo encontrar e criar issues. +O ajuste fino do Backend é sempre desejado. + +Para diretrizes detalhadas de contribuição, consulte nosso arquivo [CONTRIBUTING.md](CONTRIBUTING.md). + +## Histórico de Stars + + + + + + Star History Chart + + + +--- +--- +

+ Catalyst Project +

+ +--- +--- diff --git a/README.zh-CN.md b/README.zh-CN.md index 605e28be0..94f8321d7 100644 --- a/README.zh-CN.md +++ b/README.zh-CN.md @@ -1,5 +1,5 @@ +readme_banner -![new_header](https://github.com/user-attachments/assets/e236b764-0ddc-42ff-a1f1-8fbb3d2e0e65)
@@ -13,12 +13,11 @@
-[English](README.md) | [简体中文](README.zh-CN.md) +[English](README.md) | [Español](README.es.md) | [Português](README.pt-BR.md) | [हिन्दी](README.hi.md) | [简体中文](README.zh-CN.md)
# SurfSense - 将任何 LLM 连接到您的内部知识源,并与团队成员实时聊天。NotebookLM、Perplexity 和 Glean 的开源替代方案。 SurfSense 是一个高度可定制的 AI 研究助手,可以连接外部数据源,如搜索引擎(SearxNG、Tavily、LinkUp)、Google Drive、Slack、Microsoft Teams、Linear、Jira、ClickUp、Confluence、BookStack、Gmail、Notion、YouTube、GitHub、Discord、Airtable、Google Calendar、Luma、Circleback、Elasticsearch、Obsidian 等,未来还会支持更多。 @@ -30,7 +29,7 @@ SurfSense 是一个高度可定制的 AI 研究助手,可以连接外部数据 # 视频演示 -https://github.com/user-attachments/assets/42a29ea1-d4d8-4213-9c69-972b5b806d58 +https://github.com/user-attachments/assets/cc0c84d3-1f2f-4f7a-b519-2ecce22310b1 ## 播客示例 @@ -44,32 +43,27 @@ https://github.com/user-attachments/assets/a0a16566-6967-4374-ac51-9b3e07fbecd7 ### 💡 **理念**: - NotebookLM、Perplexity 和 Glean 的开源替代方案。将任何 LLM 连接到您的内部知识源,并与团队实时协作。 - ### 📁 **支持多种文件格式上传** - 将您个人文件中的内容(文档、图像、视频,支持 **50+ 种文件扩展名**)保存到您自己的个人知识库。 - ### 🔍 **强大的搜索功能** - 快速研究或查找已保存内容中的任何信息。 - ### 💬 **与已保存内容对话** - 使用自然语言交互并获得引用答案。 - ### 📄 **引用答案** - 像 Perplexity 一样获得带引用的答案。 - +### 🧩 **通用兼容性** +- 通过 OpenAI 规范和 LiteLLM 连接几乎任何推理提供商。 ### 🔔 **隐私保护与本地 LLM 支持** -- 完美支持 Ollama 本地大语言模型。 - +- 完美支持 vLLM 和 Ollama 等本地大语言模型。 ### 🏠 **可自托管** - 开源且易于本地部署。 - ### 👥 **团队协作与 RBAC** - 搜索空间的基于角色的访问控制 - 使用可自定义的角色(所有者、管理员、编辑者、查看者)邀请团队成员 - 对文档、聊天、连接器和设置的细粒度权限控制 - 在组织内安全共享知识库 - -### 🎙️ **播客功能** +- 团队聊天实时更新,支持评论线程中的"关于聊天的讨论" +### 🎙️ 播客功能 - 超快速播客生成代理(在 20 秒内创建 3 分钟播客) - 将聊天对话转换为引人入胜的音频内容 - 支持本地 TTS 提供商(Kokoro TTS) @@ -119,14 +113,15 @@ https://github.com/user-attachments/assets/a0a16566-6967-4374-ac51-9b3e07fbecd7 **音频/视频**(通过 STT 服务):`.mp3`、`.wav`、`.mp4`、`.webm` 等 -### 🔖 **跨浏览器扩展** -- SurfSense 扩展可用于保存您喜欢的任何网页 -- 主要用途是保存需要身份验证的受保护网页 +### 🔖 跨浏览器扩展 +- SurfSense 扩展可用于保存您喜欢的任何网页。 +- 主要用途是保存需要身份验证的受保护网页。 ## 功能请求与未来规划 + **SurfSense 正在积极开发中。** 虽然它还未达到生产就绪状态,但您可以帮助我们加快进度。 加入 [SurfSense Discord](https://discord.gg/ejRNvftDp9) 一起塑造 SurfSense 的未来! @@ -238,102 +233,11 @@ Docker 和手动安装指南都包含适用于 Windows、macOS 和 Linux 的详 - 其他根据用例需要的 API 密钥 - -## 技术栈 - - - ### **后端** - -- **FastAPI**:现代、快速的 Python Web 框架,用于构建 API - -- **PostgreSQL with pgvector**:具有向量搜索功能的数据库,用于相似性搜索 - -- **SQLAlchemy**:SQL 工具包和 ORM(对象关系映射),用于数据库交互 - -- **Alembic**:SQLAlchemy 的数据库迁移工具 - -- **FastAPI Users**:使用 JWT 和 OAuth 支持的身份验证和用户管理 - -- **深度代理**:基于 LangGraph 构建的自定义代理框架,用于推理和行动的 AI 代理,支持可配置工具 - -- **LangGraph**:用于开发具有对话持久性的有状态 AI 代理的框架 - -- **LangChain**:用于开发 AI 驱动应用程序的框架 - -- **LiteLLM**:通用 LLM 集成,支持 100+ 种模型(OpenAI、Anthropic、Ollama 等) - -- **Rerankers**:先进的结果排序,提高搜索相关性 - -- **混合搜索**:结合向量相似性和全文搜索,使用倒数排名融合 (RRF) 获得最佳结果 - -- **向量嵌入**:文档和文本嵌入,用于语义搜索 - -- **pgvector**:PostgreSQL 扩展,用于高效的向量相似性操作 - -- **Redis**:内存数据结构存储,用作 Celery 的消息代理和结果后端 - -- **Celery**:分布式任务队列,用于处理异步后台任务(文档处理、播客生成等) - -- **Flower**:Celery 任务队列的实时监控和管理工具 - -- **Chonkie**:先进的文档分块和嵌入库 - - ---- - ### **前端** - -- **Next.js**:React 框架,具有应用路由器、服务器组件、自动代码拆分和优化渲染功能 - -- **React**:用于构建用户界面的 JavaScript 库 - -- **TypeScript**:JavaScript 的静态类型检查,提升代码质量和开发体验 - -- **Vercel AI SDK Kit UI Stream Protocol**:创建可扩展的聊天 UI - -- **Tailwind CSS**:实用优先的 CSS 框架,用于构建自定义 UI 设计 - -- **Shadcn**:无头组件库 - -- **Motion(Framer Motion)**:React 动画库 - - - ### **DevOps** - -- **Docker**:容器平台,用于跨环境的一致部署 - -- **Docker Compose**:用于定义和运行多容器 Docker 应用程序的工具 - -- **pgAdmin**:Docker 设置中包含的基于 Web 的 PostgreSQL 管理工具 - - -### **扩展** -基于 Plasmo 的 Manifest v3 - - ## 贡献 非常欢迎贡献!贡献可以小到一个 ⭐,甚至是发现和创建问题。 后端的微调总是受欢迎的。 -### 添加新的代理工具 - -想要为 SurfSense 代理添加新工具?非常简单: - -1. 在 `surfsense_backend/app/agents/new_chat/tools/my_tool.py` 中创建您的工具文件 -2. 在 `registry.py` 中注册: - -```python -ToolDefinition( - name="my_tool", - description="What my tool does", - factory=lambda deps: create_my_tool( - search_space_id=deps["search_space_id"], - db_session=deps["db_session"], - ), - requires=["search_space_id", "db_session"], -), -``` - 有关详细的贡献指南,请参阅我们的 [CONTRIBUTING.md](CONTRIBUTING.md) 文件。 ## Star 历史 diff --git a/surfsense_web/app/(home)/announcements/page.tsx b/surfsense_web/app/(home)/announcements/page.tsx new file mode 100644 index 000000000..5707a6182 --- /dev/null +++ b/surfsense_web/app/(home)/announcements/page.tsx @@ -0,0 +1,350 @@ +"use client"; + +import { + Bell, + BellOff, + CheckCheck, + ExternalLink, + Filter, + Info, + type Megaphone, + Rocket, + Wrench, + X, + Zap, +} from "lucide-react"; +import Link from "next/link"; +import { useState } from "react"; +import { Badge } from "@/components/ui/badge"; +import { Button } from "@/components/ui/button"; +import { + Card, + CardContent, + CardDescription, + CardFooter, + CardHeader, + CardTitle, +} from "@/components/ui/card"; +import { + DropdownMenu, + DropdownMenuCheckboxItem, + DropdownMenuContent, + DropdownMenuLabel, + DropdownMenuSeparator, + DropdownMenuTrigger, +} from "@/components/ui/dropdown-menu"; +import { Separator } from "@/components/ui/separator"; +import { Tooltip, TooltipContent, TooltipProvider, TooltipTrigger } from "@/components/ui/tooltip"; +import type { AnnouncementCategory } from "@/contracts/types/announcement.types"; +import { type AnnouncementWithState, useAnnouncements } from "@/hooks/use-announcements"; +import { formatRelativeDate } from "@/lib/format-date"; + +// --------------------------------------------------------------------------- +// Category configuration +// --------------------------------------------------------------------------- + +const categoryConfig: Record< + AnnouncementCategory, + { + label: string; + icon: typeof Megaphone; + color: string; + badgeVariant: "default" | "secondary" | "destructive" | "outline"; + } +> = { + feature: { + label: "Feature", + icon: Rocket, + color: "text-emerald-500", + badgeVariant: "default", + }, + update: { + label: "Update", + icon: Zap, + color: "text-blue-500", + badgeVariant: "secondary", + }, + maintenance: { + label: "Maintenance", + icon: Wrench, + color: "text-amber-500", + badgeVariant: "outline", + }, + info: { + label: "Info", + icon: Info, + color: "text-muted-foreground", + badgeVariant: "secondary", + }, +}; + +// --------------------------------------------------------------------------- +// Announcement card +// --------------------------------------------------------------------------- + +function AnnouncementCard({ + announcement, + onMarkRead, + onDismiss, +}: { + announcement: AnnouncementWithState; + onMarkRead: (id: string) => void; + onDismiss: (id: string) => void; +}) { + const config = categoryConfig[announcement.category]; + const Icon = config.icon; + + return ( + + +
+
+
+ +
+
+
+ {announcement.title} + + {config.label} + + {announcement.isImportant && ( + + + Important + + )} + {!announcement.isRead && ( + + )} +
+ + {formatRelativeDate(announcement.date)} + +
+
+ + {/* Actions */} +
+ {!announcement.isRead && ( + + + + + Mark as read + + )} + + + + + Dismiss + +
+
+
+ + +

{announcement.description}

+
+ + {announcement.link && ( + + + + )} +
+ ); +} + +// --------------------------------------------------------------------------- +// Empty state +// --------------------------------------------------------------------------- + +function EmptyState({ hasFilters }: { hasFilters: boolean }) { + return ( +
+
+ {hasFilters ? ( + + ) : ( + + )} +
+

+ {hasFilters ? "No matching announcements" : "No announcements"} +

+

+ {hasFilters + ? "Try adjusting your filters to see more announcements." + : "You're all caught up! New announcements will appear here."} +

+
+ ); +} + +// --------------------------------------------------------------------------- +// Page +// --------------------------------------------------------------------------- + +export default function AnnouncementsPage() { + const [activeCategories, setActiveCategories] = useState([]); + const [showOnlyUnread, setShowOnlyUnread] = useState(false); + + const { announcements, unreadCount, markRead, markAllRead, dismiss } = useAnnouncements({ + includeDismissed: false, + }); + + // Apply local filters + const filteredAnnouncements = announcements.filter((a) => { + if (activeCategories.length > 0 && !activeCategories.includes(a.category)) return false; + if (showOnlyUnread && a.isRead) return false; + return true; + }); + + const hasActiveFilters = activeCategories.length > 0 || showOnlyUnread; + + const toggleCategory = (cat: AnnouncementCategory) => { + setActiveCategories((prev) => + prev.includes(cat) ? prev.filter((c) => c !== cat) : [...prev, cat] + ); + }; + + return ( + +
+ {/* Header */} +
+
+
+

+ Announcements +

+
+
+
+ + {/* Content */} +
+ {/* Toolbar */} +
+
+ {/* Category filter dropdown */} + + + + + + Categories + + {(Object.keys(categoryConfig) as AnnouncementCategory[]).map((cat) => { + const cfg = categoryConfig[cat]; + const CatIcon = cfg.icon; + return ( + toggleCategory(cat)} + > + + {cfg.label} + + ); + })} + + setShowOnlyUnread((v) => !v)} + > + + Unread only + + + + + {hasActiveFilters && ( + + )} +
+ + {/* Mark all read */} + {unreadCount > 0 && ( + + )} +
+ + + + {/* Announcement list */} + {filteredAnnouncements.length === 0 ? ( + + ) : ( +
+ {filteredAnnouncements.map((announcement) => ( + + ))} +
+ )} +
+
+
+ ); +} diff --git a/surfsense_web/app/layout.tsx b/surfsense_web/app/layout.tsx index 047baa27b..5e8fa394f 100644 --- a/surfsense_web/app/layout.tsx +++ b/surfsense_web/app/layout.tsx @@ -2,6 +2,7 @@ import type { Metadata, Viewport } from "next"; import "./globals.css"; import { RootProvider } from "fumadocs-ui/provider/next"; import { Roboto } from "next/font/google"; +import { AnnouncementToastProvider } from "@/components/announcements/AnnouncementToastProvider"; import { ElectricProvider } from "@/components/providers/ElectricProvider"; import { GlobalLoadingProvider } from "@/components/providers/GlobalLoadingProvider"; import { I18nProvider } from "@/components/providers/I18nProvider"; @@ -124,6 +125,7 @@ export default function RootLayout({ + diff --git a/surfsense_web/components/LanguageSwitcher.tsx b/surfsense_web/components/LanguageSwitcher.tsx index 76ab452cb..6fdef4ca0 100644 --- a/surfsense_web/components/LanguageSwitcher.tsx +++ b/surfsense_web/components/LanguageSwitcher.tsx @@ -21,6 +21,9 @@ export function LanguageSwitcher() { // Supported languages configuration const languages = [ { code: "en" as const, name: "English", flag: "🇺🇸" }, + { code: "es" as const, name: "Español", flag: "🇪🇸" }, + { code: "pt" as const, name: "Português", flag: "🇧🇷" }, + { code: "hi" as const, name: "हिन्दी", flag: "🇮🇳" }, { code: "zh" as const, name: "简体中文", flag: "🇨🇳" }, ]; @@ -29,7 +32,7 @@ export function LanguageSwitcher() { * Updates locale in context and localStorage */ const handleLanguageChange = (newLocale: string) => { - setLocale(newLocale as "en" | "zh"); + setLocale(newLocale as "en" | "es" | "pt" | "hi" | "zh"); }; return ( diff --git a/surfsense_web/components/announcements/AnnouncementToastProvider.tsx b/surfsense_web/components/announcements/AnnouncementToastProvider.tsx new file mode 100644 index 000000000..cf955fe0f --- /dev/null +++ b/surfsense_web/components/announcements/AnnouncementToastProvider.tsx @@ -0,0 +1,90 @@ +"use client"; + +import { Megaphone } from "lucide-react"; +import { useEffect, useRef } from "react"; +import { toast } from "sonner"; +import type { Announcement } from "@/contracts/types/announcement.types"; +import { announcements } from "@/lib/announcements/announcements-data"; +import { + isAnnouncementToasted, + markAnnouncementRead, + markAnnouncementToasted, +} from "@/lib/announcements/announcements-storage"; + +/** Map announcement category to the Sonner toast method */ +const categoryToVariant: Record = { + update: "info", + feature: "success", + maintenance: "warning", + info: "info", +}; + +/** Show a single announcement as a toast */ +function showAnnouncementToast(announcement: Announcement) { + const variant = categoryToVariant[announcement.category] ?? "info"; + + const options = { + description: truncateText(announcement.description, 120), + duration: 12000, + icon: , + action: announcement.link + ? { + label: announcement.link.label, + onClick: () => { + if (announcement.link?.url.startsWith("http")) { + window.open(announcement.link.url, "_blank"); + } else if (announcement.link?.url) { + window.location.href = announcement.link.url; + } + }, + } + : undefined, + onDismiss: () => { + markAnnouncementRead(announcement.id); + }, + }; + + toast[variant](announcement.title, options); + markAnnouncementToasted(announcement.id); +} + +/** + * Global provider that shows important announcements as toast notifications. + * + * Place this component once at the root layout level (alongside ). + * On mount, it checks for unread important announcements that haven't been + * shown as toasts yet, and displays them with a short stagger delay. + */ +export function AnnouncementToastProvider() { + const hasChecked = useRef(false); + + useEffect(() => { + // Only run once per page load + if (hasChecked.current) return; + hasChecked.current = true; + + // Small delay to let the page settle before showing toasts + const timer = setTimeout(() => { + const importantUntoasted = announcements.filter( + (a) => a.isImportant && !isAnnouncementToasted(a.id) + ); + + // Show each important announcement as a toast with stagger + for (let i = 0; i < importantUntoasted.length; i++) { + const announcement = importantUntoasted[i]; + setTimeout(() => showAnnouncementToast(announcement), i * 800); + } + }, 1500); // Initial delay for page to settle + + return () => clearTimeout(timer); + }, []); + + // This component renders nothing — it only triggers side effects + return null; +} + +/** Truncate text to a maximum length, adding ellipsis if needed */ +function truncateText(text: string, maxLength: number): string { + if (text.length <= maxLength) return text; + return `${text.slice(0, maxLength).trimEnd()}...`; +} diff --git a/surfsense_web/components/homepage/footer-new.tsx b/surfsense_web/components/homepage/footer-new.tsx index e52ab09b9..4bbff0cbd 100644 --- a/surfsense_web/components/homepage/footer-new.tsx +++ b/surfsense_web/components/homepage/footer-new.tsx @@ -33,6 +33,10 @@ export function FooterNew() { title: "Contact Us", href: "/contact", }, + { + title: "Announcements", + href: "/announcements", + }, ]; const socials = [ diff --git a/surfsense_web/components/homepage/navbar.tsx b/surfsense_web/components/homepage/navbar.tsx index 670e3c810..fd118b50a 100644 --- a/surfsense_web/components/homepage/navbar.tsx +++ b/surfsense_web/components/homepage/navbar.tsx @@ -4,6 +4,7 @@ import { IconBrandGithub, IconBrandReddit, IconMenu2, + IconSpeakerphone, IconX, } from "@tabler/icons-react"; import { AnimatePresence, motion } from "motion/react"; @@ -12,6 +13,7 @@ import { useEffect, useState } from "react"; import { SignInButton } from "@/components/auth/sign-in-button"; import { Logo } from "@/components/Logo"; import { ThemeTogglerComponent } from "@/components/theme/theme-toggle"; +import { useAnnouncements } from "@/hooks/use-announcements"; import { useGithubStars } from "@/hooks/use-github-stars"; import { cn } from "@/lib/utils"; @@ -47,7 +49,11 @@ export const Navbar = () => { const DesktopNav = ({ navItems, isScrolled }: any) => { const [hovered, setHovered] = useState(null); + const [mounted, setMounted] = useState(false); const { compactFormat: githubStars, loading: loadingGithubStars } = useGithubStars(); + const { unreadCount } = useAnnouncements(); + + useEffect(() => setMounted(true), []); return ( { @@ -118,6 +124,17 @@ const DesktopNav = ({ navItems, isScrolled }: any) => { )} + + + {mounted && unreadCount > 0 && ( + + {unreadCount > 99 ? "99+" : unreadCount} + + )} +
@@ -127,7 +144,11 @@ const DesktopNav = ({ navItems, isScrolled }: any) => { const MobileNav = ({ navItems, isScrolled }: any) => { const [open, setOpen] = useState(false); + const [mounted, setMounted] = useState(false); const { compactFormat: githubStars, loading: loadingGithubStars } = useGithubStars(); + const { unreadCount } = useAnnouncements(); + + useEffect(() => setMounted(true), []); return ( { )} + + + {mounted && unreadCount > 0 && ( + + {unreadCount > 99 ? "99+" : unreadCount} + + )} + diff --git a/surfsense_web/components/layout/providers/LayoutDataProvider.tsx b/surfsense_web/components/layout/providers/LayoutDataProvider.tsx index ed96b84ca..aa6d2984d 100644 --- a/surfsense_web/components/layout/providers/LayoutDataProvider.tsx +++ b/surfsense_web/components/layout/providers/LayoutDataProvider.tsx @@ -2,7 +2,15 @@ import { useQuery, useQueryClient } from "@tanstack/react-query"; import { useAtomValue, useSetAtom } from "jotai"; -import { AlertTriangle, Inbox, LogOut, PencilIcon, SquareLibrary, Trash2 } from "lucide-react"; +import { + AlertTriangle, + Inbox, + LogOut, + Megaphone, + PencilIcon, + SquareLibrary, + Trash2, +} from "lucide-react"; import { useParams, usePathname, useRouter } from "next/navigation"; import { useTranslations } from "next-intl"; import { useTheme } from "next-themes"; @@ -23,6 +31,7 @@ import { } from "@/components/ui/dialog"; import { Input } from "@/components/ui/input"; import { isPageLimitExceededMetadata } from "@/contracts/types/inbox.types"; +import { useAnnouncements } from "@/hooks/use-announcements"; import { useInbox } from "@/hooks/use-inbox"; import { searchSpacesApiService } from "@/lib/apis/search-spaces-api.service"; import { logout } from "@/lib/auth-utils"; @@ -65,6 +74,9 @@ export function LayoutDataProvider({ const queryClient = useQueryClient(); const { theme, setTheme } = useTheme(); + // Announcements + const { unreadCount: announcementUnreadCount } = useAnnouncements(); + // Atoms const { data: user } = useAtomValue(currentUserAtom); const { data: searchSpacesData, refetch: refetchSearchSpaces } = useAtomValue(searchSpacesAtom); @@ -293,8 +305,15 @@ export function LayoutDataProvider({ icon: SquareLibrary, isActive: pathname?.includes("/documents"), }, + { + title: "Announcements", + url: "/announcements", + icon: Megaphone, + isActive: pathname?.includes("/announcements"), + badge: announcementUnreadCount > 0 ? formatInboxCount(announcementUnreadCount) : undefined, + }, ], - [searchSpaceId, pathname, isInboxSidebarOpen, totalUnreadCount] + [searchSpaceId, pathname, isInboxSidebarOpen, totalUnreadCount, announcementUnreadCount] ); // Handlers diff --git a/surfsense_web/components/layout/ui/sidebar/SidebarUserProfile.tsx b/surfsense_web/components/layout/ui/sidebar/SidebarUserProfile.tsx index d87a01692..3ba7bb2a0 100644 --- a/surfsense_web/components/layout/ui/sidebar/SidebarUserProfile.tsx +++ b/surfsense_web/components/layout/ui/sidebar/SidebarUserProfile.tsx @@ -24,6 +24,9 @@ import type { User } from "../../types/layout.types"; // Supported languages configuration const LANGUAGES = [ { code: "en" as const, name: "English", flag: "🇺🇸" }, + { code: "es" as const, name: "Español", flag: "🇪🇸" }, + { code: "pt" as const, name: "Português", flag: "🇧🇷" }, + { code: "hi" as const, name: "हिन्दी", flag: "🇮🇳" }, { code: "zh" as const, name: "简体中文", flag: "🇨🇳" }, ]; @@ -131,7 +134,7 @@ export function SidebarUserProfile({ const initials = getInitials(user.email); const displayName = user.name || user.email.split("@")[0]; - const handleLanguageChange = (newLocale: "en" | "zh") => { + const handleLanguageChange = (newLocale: "en" | "es" | "pt" | "hi" | "zh") => { setLocale(newLocale); }; diff --git a/surfsense_web/contexts/LocaleContext.tsx b/surfsense_web/contexts/LocaleContext.tsx index 30d2b2e80..405fa4a50 100644 --- a/surfsense_web/contexts/LocaleContext.tsx +++ b/surfsense_web/contexts/LocaleContext.tsx @@ -3,9 +3,20 @@ import type React from "react"; import { createContext, useContext, useEffect, useState } from "react"; import enMessages from "../messages/en.json"; +import esMessages from "../messages/es.json"; +import hiMessages from "../messages/hi.json"; +import ptMessages from "../messages/pt.json"; import zhMessages from "../messages/zh.json"; -type Locale = "en" | "zh"; +type Locale = "en" | "es" | "pt" | "hi" | "zh"; + +const messagesMap: Record = { + en: enMessages, + es: esMessages as typeof enMessages, + pt: ptMessages as typeof enMessages, + hi: hiMessages as typeof enMessages, + zh: zhMessages as typeof enMessages, +}; interface LocaleContextType { locale: Locale; @@ -24,15 +35,15 @@ export function LocaleProvider({ children }: { children: React.ReactNode }) { const [mounted, setMounted] = useState(false); // Get messages based on current locale - const messages = locale === "zh" ? zhMessages : enMessages; + const messages = messagesMap[locale] || enMessages; // Load locale from localStorage after component mounts (client-side only) useEffect(() => { setMounted(true); if (typeof window !== "undefined") { const stored = localStorage.getItem(LOCALE_STORAGE_KEY); - if (stored === "zh") { - setLocaleState("zh"); + if (stored && (["en", "es", "pt", "hi", "zh"] as const).includes(stored as Locale)) { + setLocaleState(stored as Locale); } } }, []); diff --git a/surfsense_web/contracts/types/announcement.types.ts b/surfsense_web/contracts/types/announcement.types.ts new file mode 100644 index 000000000..3711dae6b --- /dev/null +++ b/surfsense_web/contracts/types/announcement.types.ts @@ -0,0 +1,42 @@ +/** + * Announcement system types + * + * Frontend-only announcement system that supports: + * - Multiple announcement categories (update, feature, maintenance, info) + * - Important flag for toast notifications + * - Read/dismissed state tracking via localStorage + */ + +/** Announcement category */ +export type AnnouncementCategory = "update" | "feature" | "maintenance" | "info"; + +/** Single announcement entry */ +export interface Announcement { + /** Unique identifier */ + id: string; + /** Short title */ + title: string; + /** Full description (supports basic text) */ + description: string; + /** Category for visual styling and filtering */ + category: AnnouncementCategory; + /** ISO date string of when the announcement was published */ + date: string; + /** If true, the user will see a toast notification for this announcement */ + isImportant: boolean; + /** Optional CTA link */ + link?: { + label: string; + url: string; + }; +} + +/** State stored in localStorage for tracking user interactions */ +export interface AnnouncementUserState { + /** IDs of announcements the user has read (clicked/viewed) */ + readIds: string[]; + /** IDs of important announcements already shown as toasts */ + toastedIds: string[]; + /** IDs of announcements the user has explicitly dismissed */ + dismissedIds: string[]; +} diff --git a/surfsense_web/hooks/use-announcements.ts b/surfsense_web/hooks/use-announcements.ts new file mode 100644 index 000000000..ad1e9b6fe --- /dev/null +++ b/surfsense_web/hooks/use-announcements.ts @@ -0,0 +1,119 @@ +"use client"; + +import { useCallback, useMemo, useSyncExternalStore } from "react"; +import type { Announcement, AnnouncementCategory } from "@/contracts/types/announcement.types"; +import { announcements } from "@/lib/announcements/announcements-data"; +import { + dismissAnnouncement, + getAnnouncementState, + isAnnouncementDismissed, + isAnnouncementRead, + markAllAnnouncementsRead, + markAnnouncementRead, +} from "@/lib/announcements/announcements-storage"; + +// --------------------------------------------------------------------------- +// External-store plumbing so React re-renders when localStorage changes +// --------------------------------------------------------------------------- + +let stateVersion = 0; +const listeners = new Set<() => void>(); + +function subscribe(callback: () => void) { + listeners.add(callback); + return () => listeners.delete(callback); +} + +function getSnapshot() { + return stateVersion; +} + +function getServerSnapshot() { + return 0; +} + +/** Bump the version so useSyncExternalStore triggers a re-render */ +function notify() { + stateVersion++; + for (const listener of listeners) listener(); +} + +// --------------------------------------------------------------------------- +// Enriched announcement with read/dismissed state +// --------------------------------------------------------------------------- + +export interface AnnouncementWithState extends Announcement { + isRead: boolean; + isDismissed: boolean; +} + +// --------------------------------------------------------------------------- +// Hook +// --------------------------------------------------------------------------- + +interface UseAnnouncementsOptions { + /** Filter by category */ + category?: AnnouncementCategory; + /** If true, include dismissed announcements (default: false) */ + includeDismissed?: boolean; +} + +export function useAnnouncements(options: UseAnnouncementsOptions = {}) { + const { category, includeDismissed = false } = options; + + // Subscribe to state changes (re-renders when localStorage state is bumped) + useSyncExternalStore(subscribe, getSnapshot, getServerSnapshot); + + const enriched: AnnouncementWithState[] = useMemo(() => { + let items = announcements.map((a) => ({ + ...a, + isRead: isAnnouncementRead(a.id), + isDismissed: isAnnouncementDismissed(a.id), + })); + + if (category) { + items = items.filter((a) => a.category === category); + } + + if (!includeDismissed) { + items = items.filter((a) => !a.isDismissed); + } + + // Sort by date descending (newest first) + items.sort((a, b) => new Date(b.date).getTime() - new Date(a.date).getTime()); + + return items; + // eslint-disable-next-line react-hooks/exhaustive-deps + }, [category, includeDismissed, stateVersion]); + + const unreadCount = useMemo( + () => enriched.filter((a) => !a.isRead && !a.isDismissed).length, + [enriched] + ); + + const handleMarkRead = useCallback((id: string) => { + markAnnouncementRead(id); + notify(); + }, []); + + const handleMarkAllRead = useCallback(() => { + const state = getAnnouncementState(); + const unreadIds = announcements.filter((a) => !state.readIds.includes(a.id)).map((a) => a.id); + markAllAnnouncementsRead(unreadIds); + notify(); + }, []); + + const handleDismiss = useCallback((id: string) => { + dismissAnnouncement(id); + markAnnouncementRead(id); + notify(); + }, []); + + return { + announcements: enriched, + unreadCount, + markRead: handleMarkRead, + markAllRead: handleMarkAllRead, + dismiss: handleDismiss, + }; +} diff --git a/surfsense_web/i18n/routing.ts b/surfsense_web/i18n/routing.ts index 5017b4be1..d709ff62a 100644 --- a/surfsense_web/i18n/routing.ts +++ b/surfsense_web/i18n/routing.ts @@ -7,7 +7,7 @@ import { defineRouting } from "next-intl/routing"; */ export const routing = defineRouting({ // A list of all locales that are supported - locales: ["en", "zh"], + locales: ["en", "es", "pt", "hi", "zh"], // Used when no locale matches defaultLocale: "en", diff --git a/surfsense_web/lib/announcements/announcements-data.ts b/surfsense_web/lib/announcements/announcements-data.ts new file mode 100644 index 000000000..00f199bd4 --- /dev/null +++ b/surfsense_web/lib/announcements/announcements-data.ts @@ -0,0 +1,65 @@ +import type { Announcement } from "@/contracts/types/announcement.types"; + +/** + * Static announcements data. + * + * To add a new announcement, append an entry to this array. + * Set `isImportant: true` to trigger a toast notification for the user. + * + * This file can be replaced with an API call in the future. + */ +export const announcements: Announcement[] = [ + { + id: "2026-02-12-announcement-syste", + title: "Introducing Announcements", + description: + "Stay up to date with the latest SurfSense news! Important announcements will appear as toast notifications so you never miss critical updates. Visit the Announcements page from the sidebar to browse all past announcements.", + category: "feature", + date: "2026-02-12T00:00:00Z", + isImportant: true, + link: { + label: "Learn more", + url: "/changelog", + }, + }, + // { + // id: "2026-02-10-podcast-improvements", + // title: "Podcast Generation Improvements", + // description: + // "We've improved podcast generation with faster processing, better audio quality, and support for longer documents. Try it out in any search space.", + // category: "update", + // date: "2026-02-10T00:00:00Z", + // isImportant: false, + // }, + // { + // id: "2026-02-08-scheduled-maintenance", + // title: "Scheduled Maintenance — Feb 15", + // description: + // "SurfSense will undergo scheduled maintenance on February 15, 2026 from 2:00 AM to 4:00 AM UTC. During this window, the service may be temporarily unavailable. We apologize for any inconvenience.", + // category: "maintenance", + // date: "2026-02-08T00:00:00Z", + // isImportant: true, + // }, + // { + // id: "2026-02-05-new-connectors", + // title: "New Connectors Available", + // description: + // "We've added support for new connectors including Linear, Jira, and Confluence. Connect your project management tools and start chatting with your data.", + // category: "feature", + // date: "2026-02-05T00:00:00Z", + // isImportant: false, + // link: { + // label: "View connectors", + // url: "#connectors", + // }, + // }, + // { + // id: "2026-01-28-team-collaboration", + // title: "Enhanced Team Collaboration", + // description: + // "Shared search spaces now support real-time mentions, comment threads, and role-based access control. Invite your team and collaborate more effectively.", + // category: "feature", + // date: "2026-01-28T00:00:00Z", + // isImportant: false, + // }, +]; diff --git a/surfsense_web/lib/announcements/announcements-storage.ts b/surfsense_web/lib/announcements/announcements-storage.ts new file mode 100644 index 000000000..9b55df6be --- /dev/null +++ b/surfsense_web/lib/announcements/announcements-storage.ts @@ -0,0 +1,107 @@ +import type { AnnouncementUserState } from "@/contracts/types/announcement.types"; + +const STORAGE_KEY = "surfsense_announcements_state"; + +const defaultState: AnnouncementUserState = { + readIds: [], + toastedIds: [], + dismissedIds: [], +}; + +/** + * Get the current announcement user state from localStorage + */ +export function getAnnouncementState(): AnnouncementUserState { + if (typeof window === "undefined") return defaultState; + + try { + const raw = localStorage.getItem(STORAGE_KEY); + if (!raw) return defaultState; + const parsed = JSON.parse(raw) as Partial; + return { + readIds: Array.isArray(parsed.readIds) ? parsed.readIds : [], + toastedIds: Array.isArray(parsed.toastedIds) ? parsed.toastedIds : [], + dismissedIds: Array.isArray(parsed.dismissedIds) ? parsed.dismissedIds : [], + }; + } catch { + return defaultState; + } +} + +/** + * Save announcement user state to localStorage + */ +function saveAnnouncementState(state: AnnouncementUserState): void { + if (typeof window === "undefined") return; + try { + localStorage.setItem(STORAGE_KEY, JSON.stringify(state)); + } catch { + // Silently fail if localStorage is full or unavailable + } +} + +/** + * Mark an announcement as read + */ +export function markAnnouncementRead(id: string): void { + const state = getAnnouncementState(); + if (!state.readIds.includes(id)) { + state.readIds.push(id); + saveAnnouncementState(state); + } +} + +/** + * Mark all announcements as read + */ +export function markAllAnnouncementsRead(ids: string[]): void { + const state = getAnnouncementState(); + const newIds = ids.filter((id) => !state.readIds.includes(id)); + if (newIds.length > 0) { + state.readIds.push(...newIds); + saveAnnouncementState(state); + } +} + +/** + * Dismiss an announcement (hide it from the list) + */ +export function dismissAnnouncement(id: string): void { + const state = getAnnouncementState(); + if (!state.dismissedIds.includes(id)) { + state.dismissedIds.push(id); + saveAnnouncementState(state); + } +} + +/** + * Mark an important announcement as already toasted (shown as toast) + */ +export function markAnnouncementToasted(id: string): void { + const state = getAnnouncementState(); + if (!state.toastedIds.includes(id)) { + state.toastedIds.push(id); + saveAnnouncementState(state); + } +} + +/** + * Check if an announcement has been read + */ +export function isAnnouncementRead(id: string): boolean { + return getAnnouncementState().readIds.includes(id); +} + +/** + * Check if an announcement has been toasted + */ +export function isAnnouncementToasted(id: string): boolean { + return getAnnouncementState().toastedIds.includes(id); +} + +/** + * Check if an announcement has been dismissed + */ +export function isAnnouncementDismissed(id: string): boolean { + return getAnnouncementState().dismissedIds.includes(id); +} diff --git a/surfsense_web/messages/es.json b/surfsense_web/messages/es.json new file mode 100644 index 000000000..9db0a99c9 --- /dev/null +++ b/surfsense_web/messages/es.json @@ -0,0 +1,818 @@ +{ + "common": { + "app_name": "SurfSense", + "welcome": "Bienvenido", + "save": "Guardar", + "cancel": "Cancelar", + "delete": "Eliminar", + "edit": "Editar", + "create": "Crear", + "update": "Actualizar", + "search": "Buscar", + "close": "Cerrar", + "confirm": "Confirmar", + "back": "Volver", + "next": "Siguiente", + "submit": "Enviar", + "yes": "Sí", + "no": "No", + "add": "Agregar", + "remove": "Eliminar", + "select": "Seleccionar", + "all": "Todo", + "none": "Ninguno", + "error": "Error", + "success": "Éxito", + "warning": "Advertencia", + "info": "Información", + "required": "Obligatorio", + "optional": "Opcional", + "retry": "Reintentar", + "owner": "Propietario", + "shared": "Compartido", + "settings": "Configuración" + }, + "auth": { + "login": "Iniciar sesión", + "register": "Registrarse", + "logout": "Cerrar sesión", + "email": "Correo electrónico", + "password": "Contraseña", + "confirm_password": "Confirmar contraseña", + "forgot_password": "¿Olvidaste tu contraseña?", + "show_password": "Mostrar contraseña", + "hide_password": "Ocultar contraseña", + "remember_me": "Recuérdame", + "sign_in": "Iniciar sesión", + "signing_in": "Iniciando sesión", + "sign_up": "Registrarse", + "sign_in_with": "Iniciar sesión con {provider}", + "dont_have_account": "¿No tienes una cuenta?", + "already_have_account": "¿Ya tienes una cuenta?", + "reset_password": "Restablecer contraseña", + "email_required": "El correo electrónico es obligatorio", + "password_required": "La contraseña es obligatoria", + "invalid_email": "Dirección de correo electrónico inválida", + "password_too_short": "La contraseña debe tener al menos 8 caracteres", + "welcome_back": "Bienvenido de nuevo", + "create_account": "Crea tu cuenta", + "login_subtitle": "Ingresa tus credenciales para acceder a tu cuenta", + "register_subtitle": "Regístrate para comenzar con SurfSense", + "or_continue_with": "O continuar con", + "by_continuing": "Al continuar, aceptas nuestros", + "terms_of_service": "Términos de servicio", + "and": "y", + "privacy_policy": "Política de privacidad", + "full_name": "Nombre completo", + "username": "Nombre de usuario", + "continue": "Continuar", + "back_to_login": "Volver al inicio de sesión", + "login_success": "Sesión iniciada correctamente", + "register_success": "Cuenta creada correctamente", + "continue_with_google": "Continuar con Google", + "cloud_dev_notice": "SurfSense Cloud está actualmente en desarrollo. Consulta", + "docs": "Documentación", + "cloud_dev_self_hosted": "para más información sobre la versión autoalojada.", + "passwords_no_match": "Las contraseñas no coinciden", + "password_mismatch": "Las contraseñas no coinciden", + "passwords_no_match_desc": "Las contraseñas que ingresaste no coinciden", + "creating_account": "Creando tu cuenta", + "creating_account_btn": "Creando cuenta", + "redirecting_login": "Redirigiendo a la página de inicio de sesión" + }, + "searchSpace": { + "create_title": "Crear espacio de búsqueda", + "create_description": "Crea un nuevo espacio de búsqueda para organizar tu conocimiento", + "name_label": "Nombre", + "name_placeholder": "Ingresa el nombre del espacio de búsqueda", + "description_label": "Descripción", + "description_placeholder": "¿Para qué es este espacio de búsqueda?", + "create_button": "Crear", + "creating": "Creando", + "all_search_spaces": "Todos los espacios de búsqueda", + "search_spaces_count": "{count, plural, =0 {Sin espacios de búsqueda} =1 {1 espacio de búsqueda} other {# espacios de búsqueda}}", + "no_search_spaces": "Aún no hay espacios de búsqueda", + "create_first_search_space": "Crea tu primer espacio de búsqueda para comenzar", + "members_count": "{count, plural, =1 {1 miembro} other {# miembros}}", + "create_new_search_space": "Crear nuevo espacio de búsqueda", + "delete_title": "Eliminar espacio de búsqueda", + "delete_confirm": "¿Estás seguro de que deseas eliminar \"{name}\"? Esta acción no se puede deshacer y eliminará permanentemente todos los datos.", + "leave": "Salir", + "leave_title": "Salir del espacio de búsqueda", + "leave_confirm": "¿Estás seguro de que deseas salir de \"{name}\"? Perderás acceso a todos los documentos y chats en este espacio de búsqueda.", + "leaving": "Saliendo...", + "welcome_title": "Bienvenido a SurfSense", + "welcome_description": "Crea tu primer espacio de búsqueda para comenzar a organizar tu conocimiento, conectar fuentes y chatear con IA.", + "create_first_button": "Crea tu primer espacio de búsqueda" + }, + "userSettings": { + "title": "Configuración de usuario", + "description": "Administra tu configuración de cuenta y acceso a la API", + "back_to_app": "Volver a la app", + "profile_nav_label": "Perfil", + "profile_nav_description": "Administra tu nombre y avatar", + "profile_title": "Perfil", + "profile_description": "Actualiza tu información personal", + "profile_avatar": "Foto de perfil", + "profile_display_name": "Nombre para mostrar", + "profile_display_name_hint": "Así aparecerá tu nombre en la aplicación", + "profile_email": "Correo electrónico", + "profile_save": "Guardar cambios", + "profile_saved": "Perfil actualizado correctamente", + "profile_save_error": "Error al actualizar el perfil", + "api_key_nav_label": "Clave API", + "api_key_nav_description": "Administra tu token de acceso a la API", + "api_key_title": "Clave API", + "api_key_description": "Usa esta clave para autenticar las solicitudes de la API", + "api_key_warning_title": "Mantenla en secreto", + "api_key_warning_description": "Tu clave API otorga acceso completo a tu cuenta. Nunca la compartas públicamente ni la incluyas en el control de versiones.", + "your_api_key": "Tu clave API", + "copied": "¡Copiado!", + "copy": "Copiar al portapapeles", + "no_api_key": "No se encontró clave API", + "usage_title": "Cómo usar", + "usage_description": "Incluye tu clave API en el encabezado de Authorization:" + }, + "dashboard": { + "title": "Panel de control", + "search_spaces": "Espacios de búsqueda", + "documents": "Documentos", + "connectors": "Conectores", + "settings": "Configuración", + "chat": "Chat", + "api_keys": "Claves API", + "profile": "Perfil", + "loading_dashboard": "Cargando panel de control", + "loading_config": "Cargando configuración", + "config_error": "Error de configuración", + "failed_load_llm_config": "No se pudo cargar tu configuración de LLM", + "error_loading_chats": "Error al cargar chats", + "loading_chat": "Cargando chat", + "loading_document": "Cargando documento", + "no_recent_chats": "No hay chats recientes", + "error_loading_space": "Error al cargar el espacio de búsqueda", + "unknown_search_space": "Espacio de búsqueda desconocido", + "delete_chat": "Eliminar chat", + "delete_chat_confirm": "¿Estás seguro de que deseas eliminar", + "delete_note": "Eliminar nota", + "delete_note_confirm": "¿Estás seguro de que deseas eliminar", + "action_cannot_undone": "Esta acción no se puede deshacer.", + "deleting": "Eliminando", + "surfsense_dashboard": "Panel de SurfSense", + "welcome_message": "Bienvenido a tu panel de SurfSense.", + "your_search_spaces": "Tus espacios de búsqueda", + "shared": "Compartido", + "create_search_space": "Crear espacio de búsqueda", + "add_new_search_space": "Agregar nuevo espacio de búsqueda", + "loading": "Cargando", + "may_take_moment": "Esto puede tomar un momento", + "error": "Error", + "something_wrong": "Algo salió mal", + "error_details": "Detalles del error", + "try_again": "Intentar de nuevo", + "go_home": "Ir al inicio", + "delete_search_space": "Eliminar espacio de búsqueda", + "delete_space_confirm": "¿Estás seguro de que deseas eliminar \"{name}\"? Esta acción no se puede deshacer. Todos los documentos y chats en este espacio de búsqueda se eliminarán permanentemente.", + "leave": "Salir", + "leave_title": "Salir del espacio de búsqueda", + "leave_confirm": "¿Estás seguro de que deseas salir de \"{name}\"? Perderás acceso a todos los documentos y chats en este espacio de búsqueda.", + "leaving": "Saliendo...", + "no_spaces_found": "No se encontraron espacios de búsqueda", + "create_first_space": "Crea tu primer espacio de búsqueda para comenzar", + "created": "Creado" + }, + "navigation": { + "home": "Inicio", + "docs": "Documentación", + "pricing": "Precios", + "contact": "Contacto", + "login": "Iniciar sesión", + "register": "Registrarse", + "dashboard": "Panel de control", + "sign_in": "Iniciar sesión", + "book_a_call": "Agendar una llamada" + }, + "nav_menu": { + "settings": "Configuración", + "platform": "Plataforma", + "chat": "Chat", + "manage_llms": "Administrar LLMs", + "sources": "Fuentes", + "add_sources": "Agregar fuentes", + "documents": "Documentos", + "upload_documents": "Subir documentos", + "add_webpages": "Agregar páginas web", + "add_youtube": "Agregar videos de YouTube", + "add_youtube_videos": "Agregar videos de YouTube", + "manage_documents": "Administrar documentos", + "connectors": "Conectores", + "add_connector": "Agregar conector", + "manage_connectors": "Administrar conectores", + "logs": "Registros", + "all_search_spaces": "Todos los espacios de búsqueda", + "team": "Equipo" + }, + "pricing": { + "title": "Precios de SurfSense", + "subtitle": "Elige lo que funcione para ti", + "community_name": "COMUNIDAD", + "enterprise_name": "EMPRESA", + "forever": "para siempre", + "contact_us": "Contáctanos", + "feature_llms": "Soporta más de 100 LLMs", + "feature_ollama": "Soporta configuraciones locales de Ollama o vLLM", + "feature_embeddings": "Más de 6000 modelos de embeddings", + "feature_files": "Más de 50 extensiones de archivo soportadas.", + "feature_podcasts": "Soporte de podcasts con proveedores TTS locales.", + "feature_sources": "Se conecta con más de 15 fuentes externas.", + "feature_extension": "Extensión para múltiples navegadores para páginas web dinámicas incluyendo contenido autenticado", + "upcoming_mindmaps": "Próximamente: Mapas mentales combinables", + "upcoming_notes": "Próximamente: Gestión de notas", + "community_desc": "Versión de código abierto con funciones potentes", + "get_started": "Comenzar", + "everything_community": "Todo lo de Comunidad", + "priority_support": "Soporte prioritario", + "access_controls": "Controles de acceso", + "collaboration": "Colaboración y funciones multijugador", + "video_gen": "Generación de video", + "advanced_security": "Funciones de seguridad avanzadas", + "enterprise_desc": "Para grandes organizaciones con necesidades específicas", + "contact_sales": "Contactar ventas" + }, + "contact": { + "title": "Contacto", + "subtitle": "Nos encantaría saber de ti.", + "we_are_here": "Estamos aquí", + "full_name": "Nombre completo", + "email_address": "Dirección de correo electrónico", + "company": "Empresa", + "message": "Mensaje", + "optional": "opcional", + "name_placeholder": "Juan Pérez", + "email_placeholder": "juan.perez@ejemplo.com", + "company_placeholder": "Ejemplo S.A.", + "message_placeholder": "Escribe tu mensaje aquí", + "submit": "Enviar", + "submitting": "Enviando...", + "name_required": "El nombre es obligatorio", + "name_too_long": "El nombre es demasiado largo", + "invalid_email": "Dirección de correo electrónico inválida", + "email_too_long": "El correo electrónico es demasiado largo", + "company_required": "La empresa es obligatoria", + "company_too_long": "El nombre de la empresa es demasiado largo", + "message_sent": "¡Mensaje enviado correctamente!", + "we_will_contact": "Nos pondremos en contacto contigo lo antes posible.", + "send_failed": "Error al enviar el mensaje", + "try_again_later": "Por favor, inténtalo de nuevo más tarde.", + "something_wrong": "Algo salió mal" + }, + "connectors": { + "title": "Conectores", + "subtitle": "Administra tus servicios conectados y fuentes de datos.", + "add_connector": "Agregar conector", + "your_connectors": "Tus conectores", + "view_manage": "Ver y administrar todos tus servicios conectados.", + "no_connectors": "No se encontraron conectores", + "no_connectors_desc": "Aún no has agregado ningún conector. Agrega uno para mejorar tus capacidades de búsqueda.", + "add_first": "Agrega tu primer conector", + "name": "Nombre", + "type": "Tipo", + "last_indexed": "Última indexación", + "periodic": "Periódico", + "actions": "Acciones", + "never": "Nunca", + "not_indexable": "No indexable", + "index_date_range": "Indexar con rango de fechas", + "quick_index": "Indexación rápida", + "quick_index_auto": "Indexación rápida (rango de fechas automático)", + "delete_connector": "Eliminar conector", + "delete_confirm": "¿Estás seguro de que deseas eliminar este conector? Esta acción no se puede deshacer.", + "select_date_range": "Seleccionar rango de fechas para indexación", + "select_date_range_desc": "Elige las fechas de inicio y fin para indexar contenido. Déjalo vacío para usar el rango predeterminado.", + "start_date": "Fecha de inicio", + "end_date": "Fecha de fin", + "pick_date": "Seleccionar fecha", + "clear_dates": "Limpiar fechas", + "last_30_days": "Últimos 30 días", + "last_year": "Último año", + "start_indexing": "Iniciar indexación", + "failed_load": "Error al cargar los conectores", + "delete_success": "Conector eliminado correctamente", + "delete_failed": "Error al eliminar el conector", + "indexing_started": "Indexación del contenido del conector iniciada", + "indexing_failed": "Error al indexar el contenido del conector" + }, + "documents": { + "title": "Documentos", + "subtitle": "Administra tus documentos y archivos.", + "no_rows_selected": "No hay filas seleccionadas", + "delete_success_count": "Se eliminaron correctamente {count} documento(s)", + "delete_partial_failed": "Algunos documentos no se pudieron eliminar", + "delete_success": "Documento eliminado correctamente", + "delete_error": "Error al eliminar documentos", + "filter_by_title": "Filtrar por título...", + "bulk_delete": "Eliminar seleccionados", + "filter_types": "Filtrar tipos", + "columns": "Columnas", + "confirm_delete": "Confirmar eliminación", + "confirm_delete_desc": "¿Estás seguro de que deseas eliminar {count} documento(s)? Esta acción no se puede deshacer.", + "uploading": "Subiendo", + "upload_success": "Documento subido correctamente", + "upload_failed": "Error al subir el documento", + "loading": "Cargando documentos", + "error_loading": "Error al cargar documentos", + "retry": "Reintentar", + "no_documents": "No se encontraron documentos", + "type": "Tipo", + "content_summary": "Resumen del contenido", + "view_full": "Ver resumen", + "filter_placeholder": "Filtrar por título...", + "rows_per_page": "Filas por página", + "refresh": "Actualizar", + "upload_documents": "Subir documentos", + "create_shared_note": "Crear nota compartida", + "processing_documents": "Procesando documentos...", + "active_tasks_count": "{count} tarea(s) activa(s)" + }, + "add_connector": { + "title": "Conecta tus herramientas", + "subtitle": "Integra con tus servicios favoritos para mejorar tus capacidades de investigación.", + "web_search": "Búsqueda web", + "messaging": "Mensajería", + "project_management": "Gestión de proyectos", + "documentation": "Documentación", + "development": "Desarrollo", + "databases": "Bases de datos", + "productivity": "Productividad", + "web_crawling": "Rastreo web", + "connect": "Conectar", + "coming_soon": "Próximamente", + "connected": "Conectado", + "manage": "Administrar", + "tavily_desc": "Busca en la web usando la API de Tavily", + "searxng_desc": "Usa tu propia instancia de SearxNG para resultados web.", + "linkup_desc": "Busca en la web usando la API de Linkup", + "elasticsearch_desc": "Conéctate a Elasticsearch para indexar y buscar documentos, registros y métricas.", + "baidu_desc": "Busca en la web china usando la API de Baidu AI Search", + "slack_desc": "Conéctate a tu espacio de trabajo de Slack para acceder a mensajes y canales.", + "teams_desc": "Conéctate a Microsoft Teams para acceder a las conversaciones de tu equipo.", + "discord_desc": "Conéctate a servidores de Discord para acceder a mensajes y canales.", + "linear_desc": "Conéctate a Linear para buscar problemas, comentarios y datos de proyectos.", + "jira_desc": "Conéctate a Jira para buscar problemas, tickets y datos de proyectos.", + "clickup_desc": "Conéctate a ClickUp para buscar tareas, comentarios y datos de proyectos.", + "notion_desc": "Conéctate a tu espacio de trabajo de Notion para acceder a páginas y bases de datos.", + "github_desc": "Conecta un PAT de GitHub para indexar código y documentos de repositorios accesibles.", + "confluence_desc": "Conéctate a Confluence para buscar páginas, comentarios y documentación.", + "bookstack_desc": "Conéctate a BookStack para buscar páginas wiki y documentación.", + "airtable_desc": "Conéctate a Airtable para buscar registros, tablas y contenido de bases de datos.", + "luma_desc": "Conéctate a Luma para buscar eventos, encuentros y reuniones.", + "circleback_desc": "Recibe notas de reuniones, transcripciones y elementos de acción de Circleback vía webhook.", + "calendar_desc": "Conéctate a Google Calendar para buscar eventos, reuniones y horarios.", + "gmail_desc": "Conéctate a tu cuenta de Gmail para buscar en tus correos electrónicos.", + "google_drive_desc": "Conéctate a Google Drive para buscar e indexar tus archivos y documentos.", + "zoom_desc": "Conéctate a Zoom para acceder a grabaciones y transcripciones de reuniones.", + "webcrawler_desc": "Rastrea e indexa contenido de cualquier página web pública." + }, + "upload_documents": { + "title": "Subir documentos", + "subtitle": "Sube tus archivos para hacerlos buscables y accesibles a través de conversaciones con IA.", + "file_size_limit": "Tamaño máximo de archivo: 50 MB por archivo.", + "upload_limits": "Límite de subida: {maxFiles} archivos, {maxSizeMB} MB en total.", + "drop_files": "Suelta los archivos aquí", + "drag_drop": "Arrastra y suelta archivos aquí", + "or_browse": "o haz clic para explorar", + "browse_files": "Explorar archivos", + "selected_files": "Archivos seleccionados ({count})", + "total_size": "Tamaño total", + "clear_all": "Limpiar todo", + "uploading_files": "Subiendo archivos", + "uploading": "Subiendo", + "upload_button": "Subir {count} {count, plural, one {archivo} other {archivos}}", + "upload_initiated": "Tarea de subida iniciada", + "upload_initiated_desc": "La subida de archivos ha comenzado", + "upload_error": "Error de subida", + "upload_error_desc": "Error al subir archivos", + "supported_file_types": "Tipos de archivo soportados", + "file_types_desc": "Estos tipos de archivo son soportados según la configuración actual de tu servicio ETL.", + "max_files_exceeded": "Límite de archivos excedido", + "max_files_exceeded_desc": "Puedes subir un máximo de {max} archivos a la vez.", + "max_size_exceeded": "Límite de tamaño excedido", + "max_size_exceeded_desc": "El tamaño total de los archivos no puede exceder {max} MB.", + "file_limit_reached": "Máximo de archivos alcanzado", + "file_limit_reached_desc": "Elimina algunos archivos para agregar más (máximo {max} archivos).", + "remaining_capacity": "{files} archivos restantes • {sizeMB} MB disponibles" + }, + "add_webpage": { + "title": "Agregar páginas web para rastreo", + "subtitle": "Ingresa URLs para rastrear y agregar a tu colección de documentos", + "label": "Ingresa URLs para rastrear", + "placeholder": "Ingresa una URL y presiona Enter", + "hint": "Agrega múltiples URLs presionando Enter después de cada una", + "tips_title": "Consejos para el rastreo de URLs:", + "tip_1": "Ingresa URLs completas incluyendo http:// o https://", + "tip_2": "Asegúrate de que los sitios web permitan el rastreo", + "tip_3": "Las páginas web públicas funcionan mejor", + "tip_4": "El rastreo puede tomar un tiempo dependiendo del tamaño del sitio web", + "cancel": "Cancelar", + "submit": "Enviar URLs para rastreo", + "submitting": "Enviando...", + "error_no_url": "Por favor agrega al menos una URL", + "error_invalid_urls": "URLs inválidas detectadas: {urls}", + "crawling_toast": "Rastreo de URL", + "crawling_toast_desc": "Iniciando proceso de rastreo de URL...", + "success_toast": "Rastreo exitoso", + "success_toast_desc": "Las URLs han sido enviadas para rastreo", + "error_toast": "Error de rastreo", + "error_toast_desc": "Error al rastrear URLs", + "error_generic": "Ocurrió un error al rastrear URLs", + "invalid_url_toast": "URL inválida", + "invalid_url_toast_desc": "Por favor ingresa una URL válida", + "duplicate_url_toast": "URL duplicada", + "duplicate_url_toast_desc": "Esta URL ya ha sido agregada" + }, + "add_youtube": { + "title": "Agregar videos de YouTube", + "subtitle": "Ingresa URLs de videos de YouTube para agregar a tu colección de documentos", + "label": "Ingresa URLs de videos de YouTube", + "placeholder": "Ingresa una URL de YouTube y presiona Enter", + "hint": "Agrega múltiples URLs de YouTube presionando Enter después de cada una", + "tips_title": "Consejos para agregar videos de YouTube:", + "tip_1": "Usa URLs estándar de YouTube (youtube.com/watch?v= o youtu.be/)", + "tip_2": "Asegúrate de que los videos sean accesibles públicamente", + "tip_3": "Formatos soportados: youtube.com/watch?v=VIDEO_ID o youtu.be/VIDEO_ID", + "tip_4": "El procesamiento puede tomar un tiempo dependiendo de la duración del video", + "preview": "Vista previa", + "cancel": "Cancelar", + "submit": "Agregar", + "processing": "Procesando...", + "error_no_video": "Por favor agrega al menos una URL de video de YouTube", + "error_invalid_urls": "URLs de YouTube inválidas detectadas: {urls}", + "processing_toast": "Procesamiento de video de YouTube", + "processing_toast_desc": "Iniciando procesamiento de video de YouTube...", + "success_toast": "Procesamiento exitoso", + "success_toast_desc": "Los videos de YouTube han sido enviados para procesamiento", + "error_toast": "Error de procesamiento", + "error_toast_desc": "Error al procesar videos de YouTube", + "error_generic": "Ocurrió un error al procesar videos de YouTube", + "invalid_url_toast": "URL de YouTube inválida", + "invalid_url_toast_desc": "Por favor ingresa una URL válida de video de YouTube", + "duplicate_url_toast": "URL duplicada", + "duplicate_url_toast_desc": "Este video de YouTube ya ha sido agregado" + }, + "settings": { + "title": "Configuración", + "subtitle": "Administra tus configuraciones de LLM y asignaciones de roles para este espacio de búsqueda.", + "back_to_dashboard": "Volver al panel de control", + "model_configs": "Configuraciones de modelos", + "models": "Modelos", + "llm_roles": "Roles de LLM", + "roles": "Roles", + "llm_role_management": "Gestión de roles de LLM", + "llm_role_desc": "Asigna tus configuraciones de LLM a roles específicos para diferentes propósitos.", + "no_llm_configs_found": "No se encontraron configuraciones de LLM. Agrega al menos un proveedor de LLM en la pestaña de Configuraciones de Modelos antes de asignar roles.", + "select_llm_config": "Selecciona una configuración de LLM", + "long_context_llm": "LLM de contexto largo", + "fast_llm": "LLM rápido", + "strategic_llm": "LLM estratégico", + "long_context_desc": "Maneja resúmenes de documentos largos y preguntas complejas", + "long_context_examples": "Análisis de documentos, síntesis de investigación, preguntas complejas", + "large_context_window": "Ventana de contexto amplia", + "deep_reasoning": "Razonamiento profundo", + "complex_analysis": "Análisis complejo", + "fast_llm_desc": "Optimizado para respuestas rápidas e interacciones en tiempo real", + "fast_llm_examples": "Búsquedas rápidas, preguntas simples, respuestas instantáneas", + "low_latency": "Baja latencia", + "quick_responses": "Respuestas rápidas", + "real_time_chat": "Chat en tiempo real", + "strategic_llm_desc": "Razonamiento avanzado para planificación y toma de decisiones estratégicas", + "strategic_llm_examples": "Planificación de flujos de trabajo, análisis estratégico, resolución de problemas complejos", + "strategic_thinking": "Pensamiento estratégico", + "long_term_planning": "Planificación a largo plazo", + "complex_reasoning": "Razonamiento complejo", + "use_cases": "Casos de uso", + "assign_llm_config": "Asignar configuración de LLM", + "unassigned": "Sin asignar", + "assigned": "Asignado", + "model": "Modelo", + "base": "Base", + "all_roles_assigned": "¡Todos los roles están asignados y listos para usar! Tu configuración de LLM está completa.", + "save_changes": "Guardar cambios", + "saving": "Guardando", + "reset": "Restablecer", + "status": "Estado", + "status_ready": "Listo", + "status_setup": "Configuración", + "complete_role_assignments": "Completa todas las asignaciones de roles para habilitar la funcionalidad completa. Cada rol tiene diferentes propósitos en tu flujo de trabajo.", + "all_roles_saved": "¡Todos los roles asignados y guardados!", + "progress": "Progreso", + "roles_assigned_count": "{assigned} de {total} roles asignados" + }, + "logs": { + "title": "Registros de tareas", + "subtitle": "Monitorea y analiza todos los registros de ejecución de tareas", + "refresh": "Actualizar", + "delete_selected": "Eliminar seleccionados", + "confirm_title": "¿Estás completamente seguro?", + "confirm_delete_desc": "Esta acción no se puede deshacer. Esto eliminará permanentemente {count} registro(s) seleccionado(s).", + "cancel": "Cancelar", + "delete": "Eliminar", + "level": "Nivel", + "status": "Estado", + "source": "Fuente", + "message": "Mensaje", + "created_at": "Fecha de creación", + "actions": "Acciones", + "system": "Sistema", + "filter_by_message": "Filtrar por mensaje...", + "filter_by": "Filtrar por", + "total_logs": "Total de registros", + "active_tasks": "Tareas activas", + "success_rate": "Tasa de éxito", + "recent_failures": "Fallos recientes", + "last_hours": "Últimas {hours} horas", + "currently_running": "Ejecutándose actualmente", + "successful": "exitoso", + "need_attention": "Requiere atención", + "no_logs": "No se encontraron registros", + "loading": "Cargando registros...", + "error_loading": "Error al cargar registros", + "columns": "Columnas", + "failed_load_summary": "Error al cargar el resumen", + "retry": "Reintentar", + "view": "Ver", + "toggle_columns": "Alternar columnas", + "rows_per_page": "Filas por página", + "view_metadata": "Ver metadatos", + "log_deleted_success": "Registro eliminado correctamente", + "log_deleted_error": "Error al eliminar el registro", + "confirm_delete_log_title": "¿Estás seguro?", + "confirm_delete_log_desc": "Esta acción no se puede deshacer. Esto eliminará permanentemente la entrada del registro.", + "deleting": "Eliminando" + }, + "onboard": { + "welcome_title": "Bienvenido a SurfSense", + "welcome_subtitle": "Vamos a configurar tus configuraciones de LLM para comenzar", + "step_of": "Paso {current} de {total}", + "percent_complete": "{percent}% completado", + "add_llm_provider": "Agregar proveedor de LLM", + "assign_llm_roles": "Asignar roles de LLM", + "setup_llm_configuration": "Configurar LLM", + "configure_providers_and_assign_roles": "Agrega tus proveedores de LLM y asígnalos a roles específicos", + "assign_llm_roles_title": "Asignar roles de LLM", + "complete_role_assignment": "Asigna tus configuraciones de LLM a roles específicos para continuar", + "setup_complete": "Configuración completa", + "configure_first_provider": "Configura tu primer proveedor de modelos", + "assign_specific_roles": "Asigna roles específicos a tus configuraciones de LLM", + "all_set": "¡Todo listo para comenzar a usar SurfSense!", + "loading_config": "Cargando tu configuración...", + "previous": "Anterior", + "next": "Siguiente", + "complete_setup": "Completar configuración", + "add_provider_instruction": "Agrega al menos un proveedor de LLM para continuar. Puedes configurar múltiples proveedores y elegir roles específicos para cada uno en el siguiente paso.", + "your_llm_configs": "Tus configuraciones de LLM", + "model": "Modelo", + "language": "Idioma", + "base": "Base", + "add_provider_title": "Agregar proveedor de LLM", + "add_provider_subtitle": "Configura tu primer proveedor de modelos para comenzar", + "add_provider_button": "Agregar proveedor", + "add_new_llm_provider": "Agregar nuevo proveedor de LLM", + "configure_new_provider": "Configura un nuevo proveedor de modelo de lenguaje para tu asistente de IA", + "config_name": "Nombre de configuración", + "config_name_required": "Nombre de configuración *", + "config_name_placeholder": "ej., Mi OpenAI GPT-4", + "provider": "Proveedor", + "provider_required": "Proveedor *", + "provider_placeholder": "Selecciona un proveedor", + "language_optional": "Idioma (opcional)", + "language_placeholder": "Selecciona idioma", + "custom_provider_name": "Nombre del proveedor personalizado *", + "custom_provider_placeholder": "ej., mi-proveedor-personalizado", + "model_name_required": "Nombre del modelo *", + "model_name_placeholder": "ej., gpt-4", + "examples": "Ejemplos", + "api_key_required": "Clave API *", + "api_key_placeholder": "Tu clave API", + "api_base_optional": "URL base de la API (opcional)", + "api_base_placeholder": "ej., https://api.openai.com/v1", + "adding": "Agregando...", + "add_provider": "Agregar proveedor", + "cancel": "Cancelar", + "assign_roles_instruction": "Asigna tus configuraciones de LLM a roles específicos. Cada rol tiene diferentes propósitos en tu flujo de trabajo.", + "no_llm_configs_found": "No se encontraron configuraciones de LLM", + "add_provider_before_roles": "Agrega al menos un proveedor de LLM en el paso anterior antes de asignar roles.", + "long_context_llm_title": "LLM de contexto largo", + "long_context_llm_desc": "Maneja resúmenes de documentos largos y preguntas complejas", + "long_context_llm_examples": "Análisis de documentos, síntesis de investigación, preguntas complejas", + "fast_llm_title": "LLM rápido", + "fast_llm_desc": "Optimizado para respuestas rápidas e interacciones en tiempo real", + "fast_llm_examples": "Búsquedas rápidas, preguntas simples, respuestas instantáneas", + "strategic_llm_title": "LLM estratégico", + "strategic_llm_desc": "Razonamiento avanzado para planificación y toma de decisiones estratégicas", + "strategic_llm_examples": "Planificación de flujos de trabajo, análisis estratégico, resolución de problemas complejos", + "use_cases": "Casos de uso", + "assign_llm_config": "Asignar configuración de LLM", + "select_llm_config": "Selecciona una configuración de LLM", + "assigned": "Asignado", + "all_roles_assigned_saved": "¡Todos los roles asignados y guardados!", + "progress": "Progreso", + "roles_assigned": "{assigned} de {total} roles asignados", + "global_configs": "Configuraciones globales", + "your_configs": "Tus configuraciones" + }, + "model_config": { + "title": "Configuraciones de modelos", + "subtitle": "Administra las configuraciones de tus proveedores de LLM y ajustes de API.", + "refresh": "Actualizar", + "loading": "Cargando configuraciones...", + "total_configs": "Total de configuraciones", + "unique_providers": "Proveedores únicos", + "system_status": "Estado del sistema", + "active": "Activo", + "your_configs": "Tus configuraciones", + "manage_configs": "Administra y configura tus proveedores de LLM", + "add_config": "Agregar configuración", + "no_configs": "Aún no hay configuraciones", + "no_configs_desc": "Agrega tus propias configuraciones de proveedor de LLM.", + "add_first_config": "Agregar primera configuración", + "created": "Creado" + }, + "breadcrumb": { + "dashboard": "Panel de control", + "search_space": "Espacio de búsqueda", + "chat": "Chat", + "documents": "Documentos", + "connectors": "Conectores", + "editor": "Editor", + "logs": "Registros", + "settings": "Configuración", + "upload_documents": "Subir documentos", + "add_youtube": "Agregar videos de YouTube", + "add_webpages": "Agregar páginas web", + "add_connector": "Agregar conector", + "manage_connectors": "Administrar conectores", + "edit_connector": "Editar conector", + "manage": "Administrar" + }, + "sidebar": { + "chats": "Chats privados", + "shared_chats": "Chats compartidos", + "search_chats": "Buscar chats", + "no_chats_found": "No se encontraron chats", + "no_shared_chats": "No hay chats compartidos", + "view_all_shared_chats": "Ver todos los chats compartidos", + "view_all_private_chats": "Ver todos los chats privados", + "no_chats": "Aún no hay chats", + "start_new_chat_hint": "Iniciar un nuevo chat", + "error_loading_chats": "Error al cargar chats", + "chat_deleted": "Chat eliminado correctamente", + "error_deleting_chat": "Error al eliminar el chat", + "delete": "Eliminar", + "try_different_search": "Intenta con un término de búsqueda diferente", + "updated": "Actualizado", + "more_options": "Más opciones", + "clear_search": "Limpiar búsqueda", + "archive": "Archivar", + "unarchive": "Restaurar", + "chat_archived": "Chat archivado", + "chat_unarchived": "Chat restaurado", + "chat_renamed": "Chat renombrado", + "error_renaming_chat": "Error al renombrar el chat", + "rename": "Renombrar", + "rename_chat": "Renombrar chat", + "rename_chat_description": "Ingresa un nuevo nombre para esta conversación.", + "chat_title_placeholder": "Título del chat", + "renaming": "Renombrando...", + "no_archived_chats": "No hay chats archivados", + "error_archiving_chat": "Error al archivar el chat", + "new_chat": "Nuevo chat", + "select_search_space": "Seleccionar espacio de búsqueda", + "manage_members": "Administrar miembros", + "search_space_settings": "Configuración del espacio de búsqueda", + "logs": "Registros", + "see_all_search_spaces": "Ver todos los espacios de búsqueda", + "expand_sidebar": "Expandir barra lateral", + "collapse_sidebar": "Contraer barra lateral", + "user_settings": "Configuración de usuario", + "language": "Idioma", + "theme": "Tema", + "light": "Claro", + "dark": "Oscuro", + "system": "Sistema", + "logout": "Cerrar sesión", + "loggingOut": "Cerrando sesión...", + "inbox": "Bandeja de entrada", + "search_inbox": "Buscar en bandeja de entrada", + "mark_all_read": "Marcar todo como leído", + "mark_as_read": "Marcar como leído", + "mentions": "Menciones", + "comments": "Comentarios", + "status": "Estado", + "no_results_found": "No se encontraron resultados", + "no_mentions": "No hay menciones", + "no_mentions_hint": "Aquí verás las menciones de otros", + "no_comments": "No hay comentarios", + "no_comments_hint": "Aquí verás las menciones y respuestas", + "no_status_updates": "No hay actualizaciones de estado", + "no_status_updates_hint": "Las actualizaciones de documentos y conectores aparecerán aquí", + "filter": "Filtrar", + "all": "Todo", + "unread": "No leído", + "connectors": "Conectores", + "all_connectors": "Todos los conectores", + "close": "Cerrar" + }, + "errors": { + "something_went_wrong": "Algo salió mal", + "try_again": "Por favor, inténtalo de nuevo", + "not_found": "No encontrado", + "unauthorized": "No autorizado", + "forbidden": "Prohibido", + "server_error": "Error del servidor", + "network_error": "Error de red" + }, + "searchSpaceSettings": { + "title": "Configuración del espacio de búsqueda", + "back_to_app": "Volver a la app", + "nav_general": "General", + "nav_general_desc": "Nombre, descripción e información básica", + "nav_agent_configs": "Configuraciones de agente", + "nav_agent_configs_desc": "Modelos LLM con prompts y citas", + "nav_role_assignments": "Asignaciones de roles", + "nav_role_assignments_desc": "Asignar configuraciones a roles de agente", + "nav_image_models": "Modelos de imagen", + "nav_image_models_desc": "Configurar modelos de generación de imágenes", + "nav_system_instructions": "Instrucciones del sistema", + "nav_system_instructions_desc": "Instrucciones de IA a nivel del espacio de búsqueda", + "nav_public_links": "Enlaces de chat públicos", + "nav_public_links_desc": "Administrar enlaces de chat compartidos públicamente", + "general_name_label": "Nombre", + "general_name_placeholder": "Ingresa el nombre del espacio de búsqueda", + "general_name_description": "Un nombre único para tu espacio de búsqueda.", + "general_description_label": "Descripción", + "general_description_placeholder": "Ingresa la descripción del espacio de búsqueda", + "general_description_description": "Una breve descripción del uso de este espacio de búsqueda.", + "general_reset": "Restablecer cambios", + "general_save": "Guardar cambios", + "general_saving": "Guardando", + "general_unsaved_changes": "Tienes cambios sin guardar. Haz clic en \"Guardar cambios\" para aplicarlos." + }, + "homepage": { + "hero_title_part1": "El espacio de trabajo con IA", + "hero_title_part2": "diseñado para equipos", + "hero_description": "Conecta cualquier LLM a tus fuentes de conocimiento internas y chatea con él en tiempo real junto a tu equipo.", + "cta_start_trial": "Comienza gratis", + "cta_explore": "Explorar", + "integrations_title": "Integraciones", + "integrations_subtitle": "Integra con las herramientas más importantes de tu equipo", + "features_title": "El centro de conocimiento impulsado por IA de tu equipo", + "features_subtitle": "Funciones potentes diseñadas para mejorar la colaboración, aumentar la productividad y optimizar tu flujo de trabajo.", + "feature_workflow_title": "Flujo de trabajo optimizado", + "feature_workflow_desc": "Centraliza todo tu conocimiento y recursos en un espacio de trabajo inteligente. Encuentra lo que necesitas al instante y acelera la toma de decisiones.", + "feature_collaboration_title": "Colaboración fluida", + "feature_collaboration_desc": "Trabaja junto a tu equipo sin esfuerzo con herramientas de colaboración en tiempo real que mantienen a todos alineados.", + "feature_customizable_title": "Totalmente personalizable", + "feature_customizable_desc": "Elige entre más de 100 LLMs líderes y llama a cualquier modelo bajo demanda sin problemas.", + "cta_transform": "Transforma cómo tu equipo", + "cta_transform_bold": "descubre y colabora", + "cta_unite_start": "Unifica el", + "cta_unite_knowledge": "conocimiento de tu equipo", + "cta_unite_middle": "en un espacio colaborativo con", + "cta_unite_search": "búsqueda inteligente", + "cta_talk_to_us": "Habla con nosotros", + "features": { + "find_ask_act": { + "title": "Encuentra, pregunta, actúa", + "description": "Obtén información instantánea, actualizaciones detalladas y respuestas con citas del conocimiento de la empresa y personal." + }, + "real_time_collab": { + "title": "Trabaja juntos en tiempo real", + "description": "Transforma los documentos de tu empresa en espacios multijugador con ediciones en vivo, contenido sincronizado y presencia." + }, + "beyond_text": { + "title": "Colabora más allá del texto", + "description": "Crea podcasts y multimedia que tu equipo puede comentar, compartir y perfeccionar juntos." + }, + "context_counts": { + "title": "Contexto donde importa", + "description": "Agrega comentarios directamente a tus chats y documentos para retroalimentación clara y en el momento." + }, + "citation_illustration_title": "Ilustración de la función de citas mostrando referencia de fuente clicable", + "referenced_chunk": "Fragmento referenciado", + "collab_illustration_label": "Ilustración de colaboración en tiempo real en un editor de texto.", + "real_time": "Tiempo real", + "collab_part1": "colabo", + "collab_part2": "raci", + "collab_part3": "ón", + "annotation_illustration_label": "Ilustración de un editor de texto con comentarios de anotación.", + "add_context_with": "Agrega contexto con", + "comments": "comentarios", + "example_comment": "¡Hablemos de esto mañana!" + } + }, + "public_chat": { + "not_found_title": "Este chat ha sido eliminado.", + "click_here": "Haz clic aquí", + "sign_in_prompt": "para iniciar sesión en SurfSense y comenzar el tuyo." + } +} diff --git a/surfsense_web/messages/hi.json b/surfsense_web/messages/hi.json new file mode 100644 index 000000000..0c5370fd0 --- /dev/null +++ b/surfsense_web/messages/hi.json @@ -0,0 +1,818 @@ +{ + "common": { + "app_name": "SurfSense", + "welcome": "स्वागत है", + "save": "सहेजें", + "cancel": "रद्द करें", + "delete": "हटाएं", + "edit": "संपादित करें", + "create": "बनाएं", + "update": "अपडेट करें", + "search": "खोजें", + "close": "बंद करें", + "confirm": "पुष्टि करें", + "back": "वापस", + "next": "अगला", + "submit": "सबमिट करें", + "yes": "हाँ", + "no": "नहीं", + "add": "जोड़ें", + "remove": "हटाएं", + "select": "चुनें", + "all": "सभी", + "none": "कोई नहीं", + "error": "त्रुटि", + "success": "सफल", + "warning": "चेतावनी", + "info": "जानकारी", + "required": "आवश्यक", + "optional": "वैकल्पिक", + "retry": "पुनः प्रयास करें", + "owner": "स्वामी", + "shared": "साझा", + "settings": "सेटिंग्स" + }, + "auth": { + "login": "लॉगिन", + "register": "पंजीकरण", + "logout": "लॉगआउट", + "email": "ईमेल", + "password": "पासवर्ड", + "confirm_password": "पासवर्ड की पुष्टि करें", + "forgot_password": "पासवर्ड भूल गए?", + "show_password": "पासवर्ड दिखाएं", + "hide_password": "पासवर्ड छुपाएं", + "remember_me": "मुझे याद रखें", + "sign_in": "साइन इन करें", + "signing_in": "साइन इन हो रहा है", + "sign_up": "साइन अप करें", + "sign_in_with": "{provider} से साइन इन करें", + "dont_have_account": "खाता नहीं है?", + "already_have_account": "पहले से खाता है?", + "reset_password": "पासवर्ड रीसेट करें", + "email_required": "ईमेल आवश्यक है", + "password_required": "पासवर्ड आवश्यक है", + "invalid_email": "अमान्य ईमेल पता", + "password_too_short": "पासवर्ड कम से कम 8 अक्षरों का होना चाहिए", + "welcome_back": "वापसी पर स्वागत है", + "create_account": "अपना खाता बनाएं", + "login_subtitle": "अपने खाते तक पहुंचने के लिए अपनी जानकारी दर्ज करें", + "register_subtitle": "SurfSense के साथ शुरू करने के लिए साइन अप करें", + "or_continue_with": "या इसके साथ जारी रखें", + "by_continuing": "जारी रखकर, आप हमारी सहमति देते हैं", + "terms_of_service": "सेवा की शर्तें", + "and": "और", + "privacy_policy": "गोपनीयता नीति", + "full_name": "पूरा नाम", + "username": "उपयोगकर्ता नाम", + "continue": "जारी रखें", + "back_to_login": "लॉगिन पर वापस जाएं", + "login_success": "सफलतापूर्वक लॉगिन हुआ", + "register_success": "खाता सफलतापूर्वक बनाया गया", + "continue_with_google": "Google के साथ जारी रखें", + "cloud_dev_notice": "SurfSense Cloud वर्तमान में विकास में है। देखें", + "docs": "दस्तावेज़", + "cloud_dev_self_hosted": "सेल्फ-होस्टेड संस्करण के बारे में अधिक जानकारी के लिए।", + "passwords_no_match": "पासवर्ड मेल नहीं खाते", + "password_mismatch": "पासवर्ड मेल नहीं खाते", + "passwords_no_match_desc": "आपके द्वारा दर्ज किए गए पासवर्ड मेल नहीं खाते", + "creating_account": "आपका खाता बनाया जा रहा है", + "creating_account_btn": "खाता बनाया जा रहा है", + "redirecting_login": "लॉगिन पेज पर रीडायरेक्ट हो रहा है" + }, + "searchSpace": { + "create_title": "सर्च स्पेस बनाएं", + "create_description": "अपने ज्ञान को व्यवस्थित करने के लिए एक नया सर्च स्पेस बनाएं", + "name_label": "नाम", + "name_placeholder": "सर्च स्पेस का नाम दर्ज करें", + "description_label": "विवरण", + "description_placeholder": "यह सर्च स्पेस किसके लिए है?", + "create_button": "बनाएं", + "creating": "बनाया जा रहा है", + "all_search_spaces": "सभी सर्च स्पेस", + "search_spaces_count": "{count, plural, =0 {कोई सर्च स्पेस नहीं} =1 {1 सर्च स्पेस} other {# सर्च स्पेस}}", + "no_search_spaces": "अभी तक कोई सर्च स्पेस नहीं", + "create_first_search_space": "शुरू करने के लिए अपना पहला सर्च स्पेस बनाएं", + "members_count": "{count, plural, =1 {1 सदस्य} other {# सदस्य}}", + "create_new_search_space": "नया सर्च स्पेस बनाएं", + "delete_title": "सर्च स्पेस हटाएं", + "delete_confirm": "क्या आप वाकई \"{name}\" को हटाना चाहते हैं? यह क्रिया पूर्ववत नहीं की जा सकती और सभी डेटा स्थायी रूप से हटा दिया जाएगा।", + "leave": "छोड़ें", + "leave_title": "सर्च स्पेस छोड़ें", + "leave_confirm": "क्या आप वाकई \"{name}\" छोड़ना चाहते हैं? आप इस सर्च स्पेस के सभी दस्तावेज़ों और चैट तक पहुंच खो देंगे।", + "leaving": "छोड़ा जा रहा है...", + "welcome_title": "SurfSense में आपका स्वागत है", + "welcome_description": "अपना ज्ञान व्यवस्थित करने, स्रोत जोड़ने और AI के साथ चैट करने के लिए अपना पहला सर्च स्पेस बनाएं।", + "create_first_button": "अपना पहला सर्च स्पेस बनाएं" + }, + "userSettings": { + "title": "उपयोगकर्ता सेटिंग्स", + "description": "अपनी खाता सेटिंग्स और API एक्सेस प्रबंधित करें", + "back_to_app": "ऐप पर वापस जाएं", + "profile_nav_label": "प्रोफ़ाइल", + "profile_nav_description": "अपना नाम और अवतार प्रबंधित करें", + "profile_title": "प्रोफ़ाइल", + "profile_description": "अपनी व्यक्तिगत जानकारी अपडेट करें", + "profile_avatar": "प्रोफ़ाइल चित्र", + "profile_display_name": "प्रदर्शन नाम", + "profile_display_name_hint": "ऐप में आपका नाम इस तरह दिखाई देगा", + "profile_email": "ईमेल", + "profile_save": "परिवर्तन सहेजें", + "profile_saved": "प्रोफ़ाइल सफलतापूर्वक अपडेट की गई", + "profile_save_error": "प्रोफ़ाइल अपडेट करने में विफल", + "api_key_nav_label": "API कुंजी", + "api_key_nav_description": "अपना API एक्सेस टोकन प्रबंधित करें", + "api_key_title": "API कुंजी", + "api_key_description": "API अनुरोधों को प्रमाणित करने के लिए इस कुंजी का उपयोग करें", + "api_key_warning_title": "इसे गुप्त रखें", + "api_key_warning_description": "आपकी API कुंजी आपके खाते तक पूर्ण पहुंच प्रदान करती है। इसे कभी सार्वजनिक रूप से साझा न करें या संस्करण नियंत्रण में शामिल न करें।", + "your_api_key": "आपकी API कुंजी", + "copied": "कॉपी किया गया!", + "copy": "क्लिपबोर्ड पर कॉपी करें", + "no_api_key": "कोई API कुंजी नहीं मिली", + "usage_title": "कैसे उपयोग करें", + "usage_description": "Authorization हेडर में अपनी API कुंजी शामिल करें:" + }, + "dashboard": { + "title": "डैशबोर्ड", + "search_spaces": "सर्च स्पेस", + "documents": "दस्तावेज़", + "connectors": "कनेक्टर", + "settings": "सेटिंग्स", + "chat": "चैट", + "api_keys": "API कुंजियां", + "profile": "प्रोफ़ाइल", + "loading_dashboard": "डैशबोर्ड लोड हो रहा है", + "loading_config": "कॉन्फ़िगरेशन लोड हो रहा है", + "config_error": "कॉन्फ़िगरेशन त्रुटि", + "failed_load_llm_config": "आपका LLM कॉन्फ़िगरेशन लोड करने में विफल", + "error_loading_chats": "चैट लोड करने में त्रुटि", + "loading_chat": "चैट लोड हो रहा है", + "loading_document": "दस्तावेज़ लोड हो रहा है", + "no_recent_chats": "कोई हालिया चैट नहीं", + "error_loading_space": "सर्च स्पेस लोड करने में त्रुटि", + "unknown_search_space": "अज्ञात सर्च स्पेस", + "delete_chat": "चैट हटाएं", + "delete_chat_confirm": "क्या आप वाकई हटाना चाहते हैं", + "delete_note": "नोट हटाएं", + "delete_note_confirm": "क्या आप वाकई हटाना चाहते हैं", + "action_cannot_undone": "यह क्रिया पूर्ववत नहीं की जा सकती।", + "deleting": "हटाया जा रहा है", + "surfsense_dashboard": "SurfSense डैशबोर्ड", + "welcome_message": "आपके SurfSense डैशबोर्ड में आपका स्वागत है।", + "your_search_spaces": "आपके सर्च स्पेस", + "shared": "साझा", + "create_search_space": "सर्च स्पेस बनाएं", + "add_new_search_space": "नया सर्च स्पेस जोड़ें", + "loading": "लोड हो रहा है", + "may_take_moment": "इसमें कुछ समय लग सकता है", + "error": "त्रुटि", + "something_wrong": "कुछ गलत हो गया", + "error_details": "त्रुटि विवरण", + "try_again": "पुनः प्रयास करें", + "go_home": "होम पर जाएं", + "delete_search_space": "सर्च स्पेस हटाएं", + "delete_space_confirm": "क्या आप वाकई \"{name}\" को हटाना चाहते हैं? यह क्रिया पूर्ववत नहीं की जा सकती। इस सर्च स्पेस के सभी दस्तावेज़ और चैट स्थायी रूप से हटा दिए जाएंगे।", + "leave": "छोड़ें", + "leave_title": "सर्च स्पेस छोड़ें", + "leave_confirm": "क्या आप वाकई \"{name}\" छोड़ना चाहते हैं? आप इस सर्च स्पेस के सभी दस्तावेज़ों और चैट तक पहुंच खो देंगे।", + "leaving": "छोड़ा जा रहा है...", + "no_spaces_found": "कोई सर्च स्पेस नहीं मिला", + "create_first_space": "शुरू करने के लिए अपना पहला सर्च स्पेस बनाएं", + "created": "बनाया गया" + }, + "navigation": { + "home": "होम", + "docs": "दस्तावेज़", + "pricing": "मूल्य निर्धारण", + "contact": "संपर्क", + "login": "लॉगिन", + "register": "पंजीकरण", + "dashboard": "डैशबोर्ड", + "sign_in": "साइन इन", + "book_a_call": "कॉल बुक करें" + }, + "nav_menu": { + "settings": "सेटिंग्स", + "platform": "प्लेटफ़ॉर्म", + "chat": "चैट", + "manage_llms": "LLM प्रबंधित करें", + "sources": "स्रोत", + "add_sources": "स्रोत जोड़ें", + "documents": "दस्तावेज़", + "upload_documents": "दस्तावेज़ अपलोड करें", + "add_webpages": "वेबपेज जोड़ें", + "add_youtube": "YouTube वीडियो जोड़ें", + "add_youtube_videos": "YouTube वीडियो जोड़ें", + "manage_documents": "दस्तावेज़ प्रबंधित करें", + "connectors": "कनेक्टर", + "add_connector": "कनेक्टर जोड़ें", + "manage_connectors": "कनेक्टर प्रबंधित करें", + "logs": "लॉग", + "all_search_spaces": "सभी सर्च स्पेस", + "team": "टीम" + }, + "pricing": { + "title": "SurfSense मूल्य निर्धारण", + "subtitle": "अपने लिए सही योजना चुनें", + "community_name": "समुदाय", + "enterprise_name": "एंटरप्राइज़", + "forever": "हमेशा के लिए", + "contact_us": "हमसे संपर्क करें", + "feature_llms": "100+ LLM का समर्थन", + "feature_ollama": "स्थानीय Ollama या vLLM सेटअप का समर्थन", + "feature_embeddings": "6000+ एम्बेडिंग मॉडल", + "feature_files": "50+ फ़ाइल एक्सटेंशन समर्थित", + "feature_podcasts": "स्थानीय TTS प्रदाताओं के साथ पॉडकास्ट समर्थन", + "feature_sources": "15+ बाहरी स्रोतों से कनेक्ट", + "feature_extension": "प्रमाणित सामग्री सहित डायनामिक वेबपेजों के लिए क्रॉस-ब्राउज़र एक्सटेंशन", + "upcoming_mindmaps": "जल्द आ रहा है: मर्ज करने योग्य माइंड मैप", + "upcoming_notes": "जल्द आ रहा है: नोट प्रबंधन", + "community_desc": "शक्तिशाली सुविधाओं के साथ ओपन सोर्स संस्करण", + "get_started": "शुरू करें", + "everything_community": "समुदाय में सब कुछ शामिल", + "priority_support": "प्राथमिकता समर्थन", + "access_controls": "एक्सेस नियंत्रण", + "collaboration": "सहयोग और मल्टीप्लेयर सुविधाएं", + "video_gen": "वीडियो जनरेशन", + "advanced_security": "उन्नत सुरक्षा सुविधाएं", + "enterprise_desc": "विशेष आवश्यकताओं वाले बड़े संगठनों के लिए", + "contact_sales": "सेल्स से संपर्क करें" + }, + "contact": { + "title": "संपर्क", + "subtitle": "हम आपसे सुनना चाहेंगे।", + "we_are_here": "हम यहां हैं", + "full_name": "पूरा नाम", + "email_address": "ईमेल पता", + "company": "कंपनी", + "message": "संदेश", + "optional": "वैकल्पिक", + "name_placeholder": "राहुल शर्मा", + "email_placeholder": "rahul.sharma@example.com", + "company_placeholder": "उदाहरण प्रा. लि.", + "message_placeholder": "अपना संदेश यहां लिखें", + "submit": "सबमिट करें", + "submitting": "सबमिट हो रहा है...", + "name_required": "नाम आवश्यक है", + "name_too_long": "नाम बहुत लंबा है", + "invalid_email": "अमान्य ईमेल पता", + "email_too_long": "ईमेल बहुत लंबा है", + "company_required": "कंपनी आवश्यक है", + "company_too_long": "कंपनी का नाम बहुत लंबा है", + "message_sent": "संदेश सफलतापूर्वक भेजा गया!", + "we_will_contact": "हम जल्द से जल्द आपसे संपर्क करेंगे।", + "send_failed": "संदेश भेजने में विफल", + "try_again_later": "कृपया बाद में पुनः प्रयास करें।", + "something_wrong": "कुछ गलत हो गया" + }, + "connectors": { + "title": "कनेक्टर", + "subtitle": "अपने कनेक्टेड सेवाओं और डेटा स्रोतों को प्रबंधित करें।", + "add_connector": "कनेक्टर जोड़ें", + "your_connectors": "आपके कनेक्टर", + "view_manage": "अपनी सभी कनेक्टेड सेवाओं को देखें और प्रबंधित करें।", + "no_connectors": "कोई कनेक्टर नहीं मिला", + "no_connectors_desc": "आपने अभी तक कोई कनेक्टर नहीं जोड़ा है। अपनी खोज क्षमताओं को बढ़ाने के लिए एक जोड़ें।", + "add_first": "अपना पहला कनेक्टर जोड़ें", + "name": "नाम", + "type": "प्रकार", + "last_indexed": "अंतिम इंडेक्सिंग", + "periodic": "आवधिक", + "actions": "क्रियाएं", + "never": "कभी नहीं", + "not_indexable": "इंडेक्स करने योग्य नहीं", + "index_date_range": "तिथि सीमा के साथ इंडेक्स करें", + "quick_index": "त्वरित इंडेक्स", + "quick_index_auto": "त्वरित इंडेक्स (स्वचालित तिथि सीमा)", + "delete_connector": "कनेक्टर हटाएं", + "delete_confirm": "क्या आप वाकई इस कनेक्टर को हटाना चाहते हैं? यह क्रिया पूर्ववत नहीं की जा सकती।", + "select_date_range": "इंडेक्सिंग के लिए तिथि सीमा चुनें", + "select_date_range_desc": "सामग्री इंडेक्स करने के लिए प्रारंभ और समाप्ति तिथियां चुनें। डिफ़ॉल्ट सीमा का उपयोग करने के लिए खाली छोड़ दें।", + "start_date": "प्रारंभ तिथि", + "end_date": "समाप्ति तिथि", + "pick_date": "तिथि चुनें", + "clear_dates": "तिथियां साफ करें", + "last_30_days": "पिछले 30 दिन", + "last_year": "पिछला वर्ष", + "start_indexing": "इंडेक्सिंग शुरू करें", + "failed_load": "कनेक्टर लोड करने में विफल", + "delete_success": "कनेक्टर सफलतापूर्वक हटाया गया", + "delete_failed": "कनेक्टर हटाने में विफल", + "indexing_started": "कनेक्टर सामग्री इंडेक्सिंग शुरू हो गई", + "indexing_failed": "कनेक्टर सामग्री इंडेक्स करने में विफल" + }, + "documents": { + "title": "दस्तावेज़", + "subtitle": "अपने दस्तावेज़ और फ़ाइलें प्रबंधित करें।", + "no_rows_selected": "कोई पंक्ति चयनित नहीं", + "delete_success_count": "{count} दस्तावेज़ सफलतापूर्वक हटाए गए", + "delete_partial_failed": "कुछ दस्तावेज़ हटाए नहीं जा सके", + "delete_success": "दस्तावेज़ सफलतापूर्वक हटाया गया", + "delete_error": "दस्तावेज़ हटाने में त्रुटि", + "filter_by_title": "शीर्षक से फ़िल्टर करें...", + "bulk_delete": "चयनित हटाएं", + "filter_types": "प्रकार फ़िल्टर करें", + "columns": "कॉलम", + "confirm_delete": "हटाने की पुष्टि करें", + "confirm_delete_desc": "क्या आप वाकई {count} दस्तावेज़ हटाना चाहते हैं? यह क्रिया पूर्ववत नहीं की जा सकती।", + "uploading": "अपलोड हो रहा है", + "upload_success": "दस्तावेज़ सफलतापूर्वक अपलोड किया गया", + "upload_failed": "दस्तावेज़ अपलोड करने में विफल", + "loading": "दस्तावेज़ लोड हो रहे हैं", + "error_loading": "दस्तावेज़ लोड करने में त्रुटि", + "retry": "पुनः प्रयास करें", + "no_documents": "कोई दस्तावेज़ नहीं मिला", + "type": "प्रकार", + "content_summary": "सामग्री सारांश", + "view_full": "सारांश देखें", + "filter_placeholder": "शीर्षक से फ़िल्टर करें...", + "rows_per_page": "प्रति पृष्ठ पंक्तियां", + "refresh": "रीफ्रेश करें", + "upload_documents": "दस्तावेज़ अपलोड करें", + "create_shared_note": "साझा नोट बनाएं", + "processing_documents": "दस्तावेज़ प्रोसेस हो रहे हैं...", + "active_tasks_count": "{count} सक्रिय कार्य" + }, + "add_connector": { + "title": "अपने टूल कनेक्ट करें", + "subtitle": "अपनी शोध क्षमताओं को बढ़ाने के लिए अपनी पसंदीदा सेवाओं के साथ एकीकृत करें।", + "web_search": "वेब खोज", + "messaging": "मैसेजिंग", + "project_management": "प्रोजेक्ट प्रबंधन", + "documentation": "दस्तावेज़ीकरण", + "development": "विकास", + "databases": "डेटाबेस", + "productivity": "उत्पादकता", + "web_crawling": "वेब क्रॉलिंग", + "connect": "कनेक्ट करें", + "coming_soon": "जल्द आ रहा है", + "connected": "कनेक्टेड", + "manage": "प्रबंधित करें", + "tavily_desc": "Tavily API का उपयोग करके वेब खोजें", + "searxng_desc": "वेब परिणामों के लिए अपनी SearxNG मेटा-सर्च इंस्टेंस का उपयोग करें।", + "linkup_desc": "Linkup API का उपयोग करके वेब खोजें", + "elasticsearch_desc": "दस्तावेज़, लॉग और मेट्रिक्स को इंडेक्स और खोजने के लिए Elasticsearch से कनेक्ट करें।", + "baidu_desc": "Baidu AI Search API का उपयोग करके चीनी वेब खोजें", + "slack_desc": "संदेशों और चैनलों तक पहुंचने के लिए अपने Slack वर्कस्पेस से कनेक्ट करें।", + "teams_desc": "अपनी टीम की बातचीत तक पहुंचने के लिए Microsoft Teams से कनेक्ट करें।", + "discord_desc": "संदेशों और चैनलों तक पहुंचने के लिए Discord सर्वरों से कनेक्ट करें।", + "linear_desc": "इश्यू, टिप्पणियां और प्रोजेक्ट डेटा खोजने के लिए Linear से कनेक्ट करें।", + "jira_desc": "इश्यू, टिकट और प्रोजेक्ट डेटा खोजने के लिए Jira से कनेक्ट करें।", + "clickup_desc": "टास्क, टिप्पणियां और प्रोजेक्ट डेटा खोजने के लिए ClickUp से कनेक्ट करें।", + "notion_desc": "पेज और डेटाबेस तक पहुंचने के लिए अपने Notion वर्कस्पेस से कनेक्ट करें।", + "github_desc": "एक्सेसिबल रिपॉजिटरी से कोड और दस्तावेज़ इंडेक्स करने के लिए GitHub PAT कनेक्ट करें।", + "confluence_desc": "पेज, टिप्पणियां और दस्तावेज़ खोजने के लिए Confluence से कनेक्ट करें।", + "bookstack_desc": "विकी पेज और दस्तावेज़ खोजने के लिए BookStack से कनेक्ट करें।", + "airtable_desc": "रिकॉर्ड, टेबल और डेटाबेस सामग्री खोजने के लिए Airtable से कनेक्ट करें।", + "luma_desc": "इवेंट, मीटअप और गैदरिंग खोजने के लिए Luma से कनेक्ट करें।", + "circleback_desc": "वेबहुक के माध्यम से Circleback से मीटिंग नोट्स, ट्रांसक्रिप्ट और एक्शन आइटम प्राप्त करें।", + "calendar_desc": "इवेंट, मीटिंग और शेड्यूल खोजने के लिए Google Calendar से कनेक्ट करें।", + "gmail_desc": "अपने ईमेल में खोज करने के लिए अपने Gmail खाते से कनेक्ट करें।", + "google_drive_desc": "अपनी फ़ाइलें और दस्तावेज़ खोजने और इंडेक्स करने के लिए Google Drive से कनेक्ट करें।", + "zoom_desc": "मीटिंग रिकॉर्डिंग और ट्रांसक्रिप्ट तक पहुंचने के लिए Zoom से कनेक्ट करें।", + "webcrawler_desc": "किसी भी सार्वजनिक वेब पेज से सामग्री क्रॉल और इंडेक्स करें।" + }, + "upload_documents": { + "title": "दस्तावेज़ अपलोड करें", + "subtitle": "AI-संचालित बातचीत के माध्यम से अपनी फ़ाइलों को खोजने योग्य और सुलभ बनाने के लिए अपलोड करें।", + "file_size_limit": "अधिकतम फ़ाइल आकार: प्रति फ़ाइल 50MB।", + "upload_limits": "अपलोड सीमा: {maxFiles} फ़ाइलें, कुल {maxSizeMB}MB।", + "drop_files": "फ़ाइलें यहां छोड़ें", + "drag_drop": "फ़ाइलें यहां खींचें और छोड़ें", + "or_browse": "या ब्राउज़ करने के लिए क्लिक करें", + "browse_files": "फ़ाइलें ब्राउज़ करें", + "selected_files": "चयनित फ़ाइलें ({count})", + "total_size": "कुल आकार", + "clear_all": "सभी साफ करें", + "uploading_files": "फ़ाइलें अपलोड हो रही हैं", + "uploading": "अपलोड हो रहा है", + "upload_button": "{count} {count, plural, one {फ़ाइल} other {फ़ाइलें}} अपलोड करें", + "upload_initiated": "अपलोड कार्य शुरू हुआ", + "upload_initiated_desc": "फ़ाइलों का अपलोड शुरू हो गया है", + "upload_error": "अपलोड त्रुटि", + "upload_error_desc": "फ़ाइलें अपलोड करने में त्रुटि", + "supported_file_types": "समर्थित फ़ाइल प्रकार", + "file_types_desc": "ये फ़ाइल प्रकार आपकी वर्तमान ETL सेवा कॉन्फ़िगरेशन के आधार पर समर्थित हैं।", + "max_files_exceeded": "फ़ाइल सीमा पार हो गई", + "max_files_exceeded_desc": "आप एक बार में अधिकतम {max} फ़ाइलें अपलोड कर सकते हैं।", + "max_size_exceeded": "आकार सीमा पार हो गई", + "max_size_exceeded_desc": "कुल फ़ाइल आकार {max}MB से अधिक नहीं हो सकता।", + "file_limit_reached": "अधिकतम फ़ाइलें पहुंच गई", + "file_limit_reached_desc": "और जोड़ने के लिए कुछ फ़ाइलें हटाएं (अधिकतम {max} फ़ाइलें)।", + "remaining_capacity": "{files} फ़ाइलें शेष • {sizeMB}MB उपलब्ध" + }, + "add_webpage": { + "title": "क्रॉलिंग के लिए वेबपेज जोड़ें", + "subtitle": "अपने दस्तावेज़ संग्रह में क्रॉल करने और जोड़ने के लिए URL दर्ज करें", + "label": "क्रॉल करने के लिए URL दर्ज करें", + "placeholder": "URL दर्ज करें और Enter दबाएं", + "hint": "प्रत्येक के बाद Enter दबाकर कई URL जोड़ें", + "tips_title": "URL क्रॉलिंग के लिए सुझाव:", + "tip_1": "http:// या https:// सहित पूरा URL दर्ज करें", + "tip_2": "सुनिश्चित करें कि वेबसाइट क्रॉलिंग की अनुमति देती है", + "tip_3": "सार्वजनिक वेबपेज सबसे अच्छे काम करते हैं", + "tip_4": "वेबसाइट के आकार के आधार पर क्रॉलिंग में कुछ समय लग सकता है", + "cancel": "रद्द करें", + "submit": "क्रॉलिंग के लिए URL सबमिट करें", + "submitting": "सबमिट हो रहा है...", + "error_no_url": "कृपया कम से कम एक URL जोड़ें", + "error_invalid_urls": "अमान्य URL पाए गए: {urls}", + "crawling_toast": "URL क्रॉलिंग", + "crawling_toast_desc": "URL क्रॉलिंग प्रक्रिया शुरू हो रही है...", + "success_toast": "क्रॉलिंग सफल", + "success_toast_desc": "URL क्रॉलिंग के लिए सबमिट किए गए हैं", + "error_toast": "क्रॉलिंग त्रुटि", + "error_toast_desc": "URL क्रॉल करने में त्रुटि", + "error_generic": "URL क्रॉल करते समय त्रुटि हुई", + "invalid_url_toast": "अमान्य URL", + "invalid_url_toast_desc": "कृपया एक मान्य URL दर्ज करें", + "duplicate_url_toast": "डुप्लिकेट URL", + "duplicate_url_toast_desc": "यह URL पहले से जोड़ा जा चुका है" + }, + "add_youtube": { + "title": "YouTube वीडियो जोड़ें", + "subtitle": "अपने दस्तावेज़ संग्रह में जोड़ने के लिए YouTube वीडियो URL दर्ज करें", + "label": "YouTube वीडियो URL दर्ज करें", + "placeholder": "YouTube URL दर्ज करें और Enter दबाएं", + "hint": "प्रत्येक के बाद Enter दबाकर कई YouTube URL जोड़ें", + "tips_title": "YouTube वीडियो जोड़ने के लिए सुझाव:", + "tip_1": "मानक YouTube URL का उपयोग करें (youtube.com/watch?v= या youtu.be/)", + "tip_2": "सुनिश्चित करें कि वीडियो सार्वजनिक रूप से सुलभ हैं", + "tip_3": "समर्थित प्रारूप: youtube.com/watch?v=VIDEO_ID या youtu.be/VIDEO_ID", + "tip_4": "वीडियो की अवधि के आधार पर प्रोसेसिंग में कुछ समय लग सकता है", + "preview": "पूर्वावलोकन", + "cancel": "रद्द करें", + "submit": "जोड़ें", + "processing": "प्रोसेस हो रहा है...", + "error_no_video": "कृपया कम से कम एक YouTube वीडियो URL जोड़ें", + "error_invalid_urls": "अमान्य YouTube URL पाए गए: {urls}", + "processing_toast": "YouTube वीडियो प्रोसेसिंग", + "processing_toast_desc": "YouTube वीडियो प्रोसेसिंग शुरू हो रही है...", + "success_toast": "प्रोसेसिंग सफल", + "success_toast_desc": "YouTube वीडियो प्रोसेसिंग के लिए सबमिट किए गए हैं", + "error_toast": "प्रोसेसिंग त्रुटि", + "error_toast_desc": "YouTube वीडियो प्रोसेस करने में त्रुटि", + "error_generic": "YouTube वीडियो प्रोसेस करते समय त्रुटि हुई", + "invalid_url_toast": "अमान्य YouTube URL", + "invalid_url_toast_desc": "कृपया एक मान्य YouTube वीडियो URL दर्ज करें", + "duplicate_url_toast": "डुप्लिकेट URL", + "duplicate_url_toast_desc": "यह YouTube वीडियो पहले से जोड़ा जा चुका है" + }, + "settings": { + "title": "सेटिंग्स", + "subtitle": "इस सर्च स्पेस के लिए अपनी LLM कॉन्फ़िगरेशन और भूमिका असाइनमेंट प्रबंधित करें।", + "back_to_dashboard": "डैशबोर्ड पर वापस जाएं", + "model_configs": "मॉडल कॉन्फ़िगरेशन", + "models": "मॉडल", + "llm_roles": "LLM भूमिकाएं", + "roles": "भूमिकाएं", + "llm_role_management": "LLM भूमिका प्रबंधन", + "llm_role_desc": "विभिन्न उद्देश्यों के लिए अपनी LLM कॉन्फ़िगरेशन को विशिष्ट भूमिकाओं में असाइन करें।", + "no_llm_configs_found": "कोई LLM कॉन्फ़िगरेशन नहीं मिला। भूमिकाएं असाइन करने से पहले मॉडल कॉन्फ़िगरेशन टैब में कम से कम एक LLM प्रदाता जोड़ें।", + "select_llm_config": "एक LLM कॉन्फ़िगरेशन चुनें", + "long_context_llm": "लंबे कॉन्टेक्स्ट LLM", + "fast_llm": "तेज़ LLM", + "strategic_llm": "रणनीतिक LLM", + "long_context_desc": "लंबे दस्तावेज़ सारांश और जटिल प्रश्नोत्तर संभालता है", + "long_context_examples": "दस्तावेज़ विश्लेषण, शोध संश्लेषण, जटिल प्रश्नोत्तर", + "large_context_window": "बड़ी कॉन्टेक्स्ट विंडो", + "deep_reasoning": "गहन तर्क", + "complex_analysis": "जटिल विश्लेषण", + "fast_llm_desc": "त्वरित प्रतिक्रियाओं और रीयल-टाइम इंटरैक्शन के लिए अनुकूलित", + "fast_llm_examples": "त्वरित खोज, सरल प्रश्न, तत्काल प्रतिक्रियाएं", + "low_latency": "कम विलंबता", + "quick_responses": "त्वरित प्रतिक्रियाएं", + "real_time_chat": "रीयल-टाइम चैट", + "strategic_llm_desc": "योजना और रणनीतिक निर्णय लेने के लिए उन्नत तर्क", + "strategic_llm_examples": "वर्कफ़्लो योजना, रणनीतिक विश्लेषण, जटिल समस्या समाधान", + "strategic_thinking": "रणनीतिक सोच", + "long_term_planning": "दीर्घकालिक योजना", + "complex_reasoning": "जटिल तर्क", + "use_cases": "उपयोग के मामले", + "assign_llm_config": "LLM कॉन्फ़िगरेशन असाइन करें", + "unassigned": "असाइन नहीं", + "assigned": "असाइन किया गया", + "model": "मॉडल", + "base": "बेस", + "all_roles_assigned": "सभी भूमिकाएं असाइन और उपयोग के लिए तैयार हैं! आपका LLM कॉन्फ़िगरेशन पूरा हो गया है।", + "save_changes": "परिवर्तन सहेजें", + "saving": "सहेजा जा रहा है", + "reset": "रीसेट करें", + "status": "स्थिति", + "status_ready": "तैयार", + "status_setup": "सेटअप", + "complete_role_assignments": "पूर्ण कार्यक्षमता सक्षम करने के लिए सभी भूमिका असाइनमेंट पूरे करें। प्रत्येक भूमिका आपके वर्कफ़्लो में अलग-अलग उद्देश्य पूरा करती है।", + "all_roles_saved": "सभी भूमिकाएं असाइन और सहेजी गई!", + "progress": "प्रगति", + "roles_assigned_count": "{total} में से {assigned} भूमिकाएं असाइन की गईं" + }, + "logs": { + "title": "कार्य लॉग", + "subtitle": "सभी कार्य निष्पादन लॉग की निगरानी और विश्लेषण करें", + "refresh": "रीफ्रेश करें", + "delete_selected": "चयनित हटाएं", + "confirm_title": "क्या आप पूरी तरह सुनिश्चित हैं?", + "confirm_delete_desc": "यह क्रिया पूर्ववत नहीं की जा सकती। यह {count} चयनित लॉग को स्थायी रूप से हटा देगी।", + "cancel": "रद्द करें", + "delete": "हटाएं", + "level": "स्तर", + "status": "स्थिति", + "source": "स्रोत", + "message": "संदेश", + "created_at": "बनाया गया", + "actions": "क्रियाएं", + "system": "सिस्टम", + "filter_by_message": "संदेश से फ़िल्टर करें...", + "filter_by": "इसके द्वारा फ़िल्टर करें", + "total_logs": "कुल लॉग", + "active_tasks": "सक्रिय कार्य", + "success_rate": "सफलता दर", + "recent_failures": "हालिया विफलताएं", + "last_hours": "पिछले {hours} घंटे", + "currently_running": "वर्तमान में चल रहा है", + "successful": "सफल", + "need_attention": "ध्यान देने की आवश्यकता", + "no_logs": "कोई लॉग नहीं मिला", + "loading": "लॉग लोड हो रहे हैं...", + "error_loading": "लॉग लोड करने में त्रुटि", + "columns": "कॉलम", + "failed_load_summary": "सारांश लोड करने में विफल", + "retry": "पुनः प्रयास करें", + "view": "देखें", + "toggle_columns": "कॉलम टॉगल करें", + "rows_per_page": "प्रति पृष्ठ पंक्तियां", + "view_metadata": "मेटाडेटा देखें", + "log_deleted_success": "लॉग सफलतापूर्वक हटाया गया", + "log_deleted_error": "लॉग हटाने में विफल", + "confirm_delete_log_title": "क्या आप सुनिश्चित हैं?", + "confirm_delete_log_desc": "यह क्रिया पूर्ववत नहीं की जा सकती। यह लॉग प्रविष्टि को स्थायी रूप से हटा देगी।", + "deleting": "हटाया जा रहा है" + }, + "onboard": { + "welcome_title": "SurfSense में आपका स्वागत है", + "welcome_subtitle": "शुरू करने के लिए अपनी LLM कॉन्फ़िगरेशन सेट करें", + "step_of": "चरण {current} / {total}", + "percent_complete": "{percent}% पूर्ण", + "add_llm_provider": "LLM प्रदाता जोड़ें", + "assign_llm_roles": "LLM भूमिकाएं असाइन करें", + "setup_llm_configuration": "LLM कॉन्फ़िगरेशन सेटअप", + "configure_providers_and_assign_roles": "अपने LLM प्रदाता जोड़ें और उन्हें विशिष्ट भूमिकाओं में असाइन करें", + "assign_llm_roles_title": "LLM भूमिकाएं असाइन करें", + "complete_role_assignment": "जारी रखने के लिए अपनी LLM कॉन्फ़िगरेशन को विशिष्ट भूमिकाओं में असाइन करें", + "setup_complete": "सेटअप पूरा हुआ", + "configure_first_provider": "अपना पहला मॉडल प्रदाता कॉन्फ़िगर करें", + "assign_specific_roles": "अपनी LLM कॉन्फ़िगरेशन को विशिष्ट भूमिकाएं असाइन करें", + "all_set": "SurfSense का उपयोग शुरू करने के लिए आप तैयार हैं!", + "loading_config": "आपकी कॉन्फ़िगरेशन लोड हो रही है...", + "previous": "पिछला", + "next": "अगला", + "complete_setup": "सेटअप पूरा करें", + "add_provider_instruction": "जारी रखने के लिए कम से कम एक LLM प्रदाता जोड़ें। आप कई प्रदाता कॉन्फ़िगर कर सकते हैं और अगले चरण में प्रत्येक के लिए विशिष्ट भूमिकाएं चुन सकते हैं।", + "your_llm_configs": "आपकी LLM कॉन्फ़िगरेशन", + "model": "मॉडल", + "language": "भाषा", + "base": "बेस", + "add_provider_title": "LLM प्रदाता जोड़ें", + "add_provider_subtitle": "शुरू करने के लिए अपना पहला मॉडल प्रदाता कॉन्फ़िगर करें", + "add_provider_button": "प्रदाता जोड़ें", + "add_new_llm_provider": "नया LLM प्रदाता जोड़ें", + "configure_new_provider": "अपने AI सहायक के लिए एक नया भाषा मॉडल प्रदाता कॉन्फ़िगर करें", + "config_name": "कॉन्फ़िगरेशन नाम", + "config_name_required": "कॉन्फ़िगरेशन नाम *", + "config_name_placeholder": "उदा., मेरा OpenAI GPT-4", + "provider": "प्रदाता", + "provider_required": "प्रदाता *", + "provider_placeholder": "प्रदाता चुनें", + "language_optional": "भाषा (वैकल्पिक)", + "language_placeholder": "भाषा चुनें", + "custom_provider_name": "कस्टम प्रदाता नाम *", + "custom_provider_placeholder": "उदा., my-custom-provider", + "model_name_required": "मॉडल नाम *", + "model_name_placeholder": "उदा., gpt-4", + "examples": "उदाहरण", + "api_key_required": "API कुंजी *", + "api_key_placeholder": "आपकी API कुंजी", + "api_base_optional": "API बेस URL (वैकल्पिक)", + "api_base_placeholder": "उदा., https://api.openai.com/v1", + "adding": "जोड़ा जा रहा है...", + "add_provider": "प्रदाता जोड़ें", + "cancel": "रद्द करें", + "assign_roles_instruction": "अपनी LLM कॉन्फ़िगरेशन को विशिष्ट भूमिकाओं में असाइन करें। प्रत्येक भूमिका आपके वर्कफ़्लो में अलग-अलग उद्देश्य पूरा करती है।", + "no_llm_configs_found": "कोई LLM कॉन्फ़िगरेशन नहीं मिला", + "add_provider_before_roles": "भूमिकाएं असाइन करने से पहले कृपया पिछले चरण में कम से कम एक LLM प्रदाता जोड़ें।", + "long_context_llm_title": "लंबे कॉन्टेक्स्ट LLM", + "long_context_llm_desc": "लंबे दस्तावेज़ सारांश और जटिल प्रश्नोत्तर संभालता है", + "long_context_llm_examples": "दस्तावेज़ विश्लेषण, शोध संश्लेषण, जटिल प्रश्नोत्तर", + "fast_llm_title": "तेज़ LLM", + "fast_llm_desc": "त्वरित प्रतिक्रियाओं और रीयल-टाइम इंटरैक्शन के लिए अनुकूलित", + "fast_llm_examples": "त्वरित खोज, सरल प्रश्न, तत्काल प्रतिक्रियाएं", + "strategic_llm_title": "रणनीतिक LLM", + "strategic_llm_desc": "योजना और रणनीतिक निर्णय लेने के लिए उन्नत तर्क", + "strategic_llm_examples": "वर्कफ़्लो योजना, रणनीतिक विश्लेषण, जटिल समस्या समाधान", + "use_cases": "उपयोग के मामले", + "assign_llm_config": "LLM कॉन्फ़िगरेशन असाइन करें", + "select_llm_config": "एक LLM कॉन्फ़िगरेशन चुनें", + "assigned": "असाइन किया गया", + "all_roles_assigned_saved": "सभी भूमिकाएं असाइन और सहेजी गई!", + "progress": "प्रगति", + "roles_assigned": "{total} में से {assigned} भूमिकाएं असाइन की गईं", + "global_configs": "वैश्विक कॉन्फ़िगरेशन", + "your_configs": "आपकी कॉन्फ़िगरेशन" + }, + "model_config": { + "title": "मॉडल कॉन्फ़िगरेशन", + "subtitle": "अपने LLM प्रदाता कॉन्फ़िगरेशन और API सेटिंग्स प्रबंधित करें।", + "refresh": "रीफ्रेश करें", + "loading": "कॉन्फ़िगरेशन लोड हो रही हैं...", + "total_configs": "कुल कॉन्फ़िगरेशन", + "unique_providers": "अद्वितीय प्रदाता", + "system_status": "सिस्टम स्थिति", + "active": "सक्रिय", + "your_configs": "आपकी कॉन्फ़िगरेशन", + "manage_configs": "अपने LLM प्रदाता प्रबंधित और कॉन्फ़िगर करें", + "add_config": "कॉन्फ़िगरेशन जोड़ें", + "no_configs": "अभी तक कोई कॉन्फ़िगरेशन नहीं", + "no_configs_desc": "अपनी LLM प्रदाता कॉन्फ़िगरेशन जोड़ें।", + "add_first_config": "पहली कॉन्फ़िगरेशन जोड़ें", + "created": "बनाया गया" + }, + "breadcrumb": { + "dashboard": "डैशबोर्ड", + "search_space": "सर्च स्पेस", + "chat": "चैट", + "documents": "दस्तावेज़", + "connectors": "कनेक्टर", + "editor": "एडिटर", + "logs": "लॉग", + "settings": "सेटिंग्स", + "upload_documents": "दस्तावेज़ अपलोड करें", + "add_youtube": "YouTube वीडियो जोड़ें", + "add_webpages": "वेबपेज जोड़ें", + "add_connector": "कनेक्टर जोड़ें", + "manage_connectors": "कनेक्टर प्रबंधित करें", + "edit_connector": "कनेक्टर संपादित करें", + "manage": "प्रबंधित करें" + }, + "sidebar": { + "chats": "निजी चैट", + "shared_chats": "साझा चैट", + "search_chats": "चैट खोजें", + "no_chats_found": "कोई चैट नहीं मिला", + "no_shared_chats": "कोई साझा चैट नहीं", + "view_all_shared_chats": "सभी साझा चैट देखें", + "view_all_private_chats": "सभी निजी चैट देखें", + "no_chats": "अभी तक कोई चैट नहीं", + "start_new_chat_hint": "नई चैट शुरू करें", + "error_loading_chats": "चैट लोड करने में त्रुटि", + "chat_deleted": "चैट सफलतापूर्वक हटाया गया", + "error_deleting_chat": "चैट हटाने में विफल", + "delete": "हटाएं", + "try_different_search": "कोई अलग खोज शब्द आज़माएं", + "updated": "अपडेट किया गया", + "more_options": "और विकल्प", + "clear_search": "खोज साफ करें", + "archive": "आर्काइव करें", + "unarchive": "पुनर्स्थापित करें", + "chat_archived": "चैट आर्काइव किया गया", + "chat_unarchived": "चैट पुनर्स्थापित किया गया", + "chat_renamed": "चैट का नाम बदला गया", + "error_renaming_chat": "चैट का नाम बदलने में विफल", + "rename": "नाम बदलें", + "rename_chat": "चैट का नाम बदलें", + "rename_chat_description": "इस वार्तालाप के लिए एक नया नाम दर्ज करें।", + "chat_title_placeholder": "चैट शीर्षक", + "renaming": "नाम बदला जा रहा है...", + "no_archived_chats": "कोई आर्काइव्ड चैट नहीं", + "error_archiving_chat": "चैट आर्काइव करने में विफल", + "new_chat": "नई चैट", + "select_search_space": "सर्च स्पेस चुनें", + "manage_members": "सदस्य प्रबंधित करें", + "search_space_settings": "सर्च स्पेस सेटिंग्स", + "logs": "लॉग", + "see_all_search_spaces": "सभी सर्च स्पेस देखें", + "expand_sidebar": "साइडबार विस्तृत करें", + "collapse_sidebar": "साइडबार संकुचित करें", + "user_settings": "उपयोगकर्ता सेटिंग्स", + "language": "भाषा", + "theme": "थीम", + "light": "लाइट", + "dark": "डार्क", + "system": "सिस्टम", + "logout": "लॉगआउट", + "loggingOut": "लॉगआउट हो रहा है...", + "inbox": "इनबॉक्स", + "search_inbox": "इनबॉक्स में खोजें", + "mark_all_read": "सभी पढ़ा हुआ चिह्नित करें", + "mark_as_read": "पढ़ा हुआ चिह्नित करें", + "mentions": "उल्लेख", + "comments": "टिप्पणियां", + "status": "स्थिति", + "no_results_found": "कोई परिणाम नहीं मिला", + "no_mentions": "कोई उल्लेख नहीं", + "no_mentions_hint": "आप यहां दूसरों के उल्लेख देखेंगे", + "no_comments": "कोई टिप्पणियां नहीं", + "no_comments_hint": "आप यहां उल्लेख और उत्तर देखेंगे", + "no_status_updates": "कोई स्थिति अपडेट नहीं", + "no_status_updates_hint": "दस्तावेज़ और कनेक्टर अपडेट यहां दिखाई देंगे", + "filter": "फ़िल्टर", + "all": "सभी", + "unread": "अपठित", + "connectors": "कनेक्टर", + "all_connectors": "सभी कनेक्टर", + "close": "बंद करें" + }, + "errors": { + "something_went_wrong": "कुछ गलत हो गया", + "try_again": "कृपया पुनः प्रयास करें", + "not_found": "नहीं मिला", + "unauthorized": "अनधिकृत", + "forbidden": "प्रतिबंधित", + "server_error": "सर्वर त्रुटि", + "network_error": "नेटवर्क त्रुटि" + }, + "searchSpaceSettings": { + "title": "सर्च स्पेस सेटिंग्स", + "back_to_app": "ऐप पर वापस जाएं", + "nav_general": "सामान्य", + "nav_general_desc": "नाम, विवरण और बुनियादी जानकारी", + "nav_agent_configs": "एजेंट कॉन्फ़िगरेशन", + "nav_agent_configs_desc": "प्रॉम्प्ट और उद्धरण के साथ LLM मॉडल", + "nav_role_assignments": "भूमिका असाइनमेंट", + "nav_role_assignments_desc": "एजेंट भूमिकाओं को कॉन्फ़िगरेशन असाइन करें", + "nav_image_models": "इमेज मॉडल", + "nav_image_models_desc": "इमेज जनरेशन मॉडल कॉन्फ़िगर करें", + "nav_system_instructions": "सिस्टम निर्देश", + "nav_system_instructions_desc": "सर्च स्पेस-व्यापी AI निर्देश", + "nav_public_links": "सार्वजनिक चैट लिंक", + "nav_public_links_desc": "सार्वजनिक रूप से साझा किए गए चैट लिंक प्रबंधित करें", + "general_name_label": "नाम", + "general_name_placeholder": "सर्च स्पेस का नाम दर्ज करें", + "general_name_description": "आपके सर्च स्पेस के लिए एक अद्वितीय नाम।", + "general_description_label": "विवरण", + "general_description_placeholder": "सर्च स्पेस का विवरण दर्ज करें", + "general_description_description": "इस सर्च स्पेस के उपयोग का संक्षिप्त विवरण।", + "general_reset": "परिवर्तन रीसेट करें", + "general_save": "परिवर्तन सहेजें", + "general_saving": "सहेजा जा रहा है", + "general_unsaved_changes": "आपके पास सहेजे नहीं गए परिवर्तन हैं। उन्हें लागू करने के लिए \"परिवर्तन सहेजें\" पर क्लिक करें।" + }, + "homepage": { + "hero_title_part1": "AI कार्यक्षेत्र", + "hero_title_part2": "टीमों के लिए बनाया गया", + "hero_description": "किसी भी LLM को अपने आंतरिक ज्ञान स्रोतों से जोड़ें और अपनी टीम के साथ रीयल-टाइम में चैट करें।", + "cta_start_trial": "मुफ़्त शुरू करें", + "cta_explore": "एक्सप्लोर करें", + "integrations_title": "एकीकरण", + "integrations_subtitle": "अपनी टीम के सबसे महत्वपूर्ण टूल के साथ एकीकृत करें", + "features_title": "आपकी टीम का AI-संचालित ज्ञान केंद्र", + "features_subtitle": "सहयोग बढ़ाने, उत्पादकता बढ़ाने और अपने वर्कफ़्लो को सुव्यवस्थित करने के लिए डिज़ाइन की गई शक्तिशाली सुविधाएं।", + "feature_workflow_title": "सुव्यवस्थित वर्कफ़्लो", + "feature_workflow_desc": "अपने सभी ज्ञान और संसाधनों को एक बुद्धिमान कार्यक्षेत्र में केंद्रित करें। तुरंत वह खोजें जो आपको चाहिए और निर्णय लेने में तेज़ी लाएं।", + "feature_collaboration_title": "सहज सहयोग", + "feature_collaboration_desc": "रीयल-टाइम सहयोग टूल के साथ आसानी से एक साथ काम करें जो आपकी पूरी टीम को संरेखित रखें।", + "feature_customizable_title": "पूरी तरह अनुकूलन योग्य", + "feature_customizable_desc": "100+ प्रमुख LLM में से चुनें और मांग पर किसी भी मॉडल को सहजता से कॉल करें।", + "cta_transform": "बदलें कि आपकी टीम कैसे", + "cta_transform_bold": "खोजती और सहयोग करती है", + "cta_unite_start": "अपनी", + "cta_unite_knowledge": "टीम के ज्ञान", + "cta_unite_middle": "को एक सहयोगी स्थान में एकजुट करें", + "cta_unite_search": "बुद्धिमान खोज के साथ", + "cta_talk_to_us": "हमसे बात करें", + "features": { + "find_ask_act": { + "title": "खोजें, पूछें, कार्य करें", + "description": "कंपनी और व्यक्तिगत ज्ञान से तत्काल जानकारी, विस्तृत अपडेट और उद्धृत उत्तर प्राप्त करें।" + }, + "real_time_collab": { + "title": "रीयल-टाइम में एक साथ काम करें", + "description": "अपनी कंपनी के दस्तावेज़ों को लाइव एडिट, सिंक्ड सामग्री और उपस्थिति के साथ मल्टीप्लेयर स्पेस में बदलें।" + }, + "beyond_text": { + "title": "टेक्स्ट से परे सहयोग करें", + "description": "पॉडकास्ट और मल्टीमीडिया बनाएं जिन पर आपकी टीम टिप्पणी कर सकती है, साझा कर सकती है और एक साथ सुधार कर सकती है।" + }, + "context_counts": { + "title": "जहां मायने रखता है वहां संदर्भ", + "description": "स्पष्ट, तात्कालिक प्रतिक्रिया के लिए सीधे अपने चैट और दस्तावेज़ों में टिप्पणियां जोड़ें।" + }, + "citation_illustration_title": "क्लिक करने योग्य स्रोत संदर्भ दिखाने वाली उद्धरण सुविधा का चित्रण", + "referenced_chunk": "संदर्भित अंश", + "collab_illustration_label": "टेक्स्ट एडिटर में रीयल-टाइम सहयोग का चित्रण।", + "real_time": "रीयल-टाइम", + "collab_part1": "सह", + "collab_part2": "यो", + "collab_part3": "ग", + "annotation_illustration_label": "एनोटेशन टिप्पणियों वाले टेक्स्ट एडिटर का चित्रण।", + "add_context_with": "संदर्भ जोड़ें", + "comments": "टिप्पणियों के साथ", + "example_comment": "इस पर कल चर्चा करते हैं!" + } + }, + "public_chat": { + "not_found_title": "यह चैट हटा दिया गया है।", + "click_here": "यहां क्लिक करें", + "sign_in_prompt": "SurfSense में लॉगिन करने और अपना शुरू करने के लिए।" + } +} diff --git a/surfsense_web/messages/pt.json b/surfsense_web/messages/pt.json new file mode 100644 index 000000000..3803e066c --- /dev/null +++ b/surfsense_web/messages/pt.json @@ -0,0 +1,818 @@ +{ + "common": { + "app_name": "SurfSense", + "welcome": "Bem-vindo", + "save": "Salvar", + "cancel": "Cancelar", + "delete": "Excluir", + "edit": "Editar", + "create": "Criar", + "update": "Atualizar", + "search": "Pesquisar", + "close": "Fechar", + "confirm": "Confirmar", + "back": "Voltar", + "next": "Próximo", + "submit": "Enviar", + "yes": "Sim", + "no": "Não", + "add": "Adicionar", + "remove": "Remover", + "select": "Selecionar", + "all": "Tudo", + "none": "Nenhum", + "error": "Erro", + "success": "Sucesso", + "warning": "Aviso", + "info": "Informação", + "required": "Obrigatório", + "optional": "Opcional", + "retry": "Tentar novamente", + "owner": "Proprietário", + "shared": "Compartilhado", + "settings": "Configurações" + }, + "auth": { + "login": "Entrar", + "register": "Cadastrar", + "logout": "Sair", + "email": "E-mail", + "password": "Senha", + "confirm_password": "Confirmar senha", + "forgot_password": "Esqueceu a senha?", + "show_password": "Mostrar senha", + "hide_password": "Ocultar senha", + "remember_me": "Lembrar de mim", + "sign_in": "Entrar", + "signing_in": "Entrando", + "sign_up": "Cadastrar", + "sign_in_with": "Entrar com {provider}", + "dont_have_account": "Não tem uma conta?", + "already_have_account": "Já tem uma conta?", + "reset_password": "Redefinir senha", + "email_required": "O e-mail é obrigatório", + "password_required": "A senha é obrigatória", + "invalid_email": "Endereço de e-mail inválido", + "password_too_short": "A senha deve ter pelo menos 8 caracteres", + "welcome_back": "Bem-vindo de volta", + "create_account": "Crie sua conta", + "login_subtitle": "Insira suas credenciais para acessar sua conta", + "register_subtitle": "Cadastre-se para começar a usar o SurfSense", + "or_continue_with": "Ou continuar com", + "by_continuing": "Ao continuar, você concorda com nossos", + "terms_of_service": "Termos de serviço", + "and": "e", + "privacy_policy": "Política de privacidade", + "full_name": "Nome completo", + "username": "Nome de usuário", + "continue": "Continuar", + "back_to_login": "Voltar ao login", + "login_success": "Login realizado com sucesso", + "register_success": "Conta criada com sucesso", + "continue_with_google": "Continuar com Google", + "cloud_dev_notice": "O SurfSense Cloud está atualmente em desenvolvimento. Consulte", + "docs": "Documentação", + "cloud_dev_self_hosted": "para mais informações sobre a versão auto-hospedada.", + "passwords_no_match": "As senhas não coincidem", + "password_mismatch": "Senhas diferentes", + "passwords_no_match_desc": "As senhas que você digitou não coincidem", + "creating_account": "Criando sua conta", + "creating_account_btn": "Criando conta", + "redirecting_login": "Redirecionando para a página de login" + }, + "searchSpace": { + "create_title": "Criar espaço de pesquisa", + "create_description": "Crie um novo espaço de pesquisa para organizar seu conhecimento", + "name_label": "Nome", + "name_placeholder": "Digite o nome do espaço de pesquisa", + "description_label": "Descrição", + "description_placeholder": "Para que é este espaço de pesquisa?", + "create_button": "Criar", + "creating": "Criando", + "all_search_spaces": "Todos os espaços de pesquisa", + "search_spaces_count": "{count, plural, =0 {Nenhum espaço de pesquisa} =1 {1 espaço de pesquisa} other {# espaços de pesquisa}}", + "no_search_spaces": "Nenhum espaço de pesquisa ainda", + "create_first_search_space": "Crie seu primeiro espaço de pesquisa para começar", + "members_count": "{count, plural, =1 {1 membro} other {# membros}}", + "create_new_search_space": "Criar novo espaço de pesquisa", + "delete_title": "Excluir espaço de pesquisa", + "delete_confirm": "Tem certeza de que deseja excluir \"{name}\"? Esta ação não pode ser desfeita e removerá permanentemente todos os dados.", + "leave": "Sair", + "leave_title": "Sair do espaço de pesquisa", + "leave_confirm": "Tem certeza de que deseja sair de \"{name}\"? Você perderá acesso a todos os documentos e chats neste espaço de pesquisa.", + "leaving": "Saindo...", + "welcome_title": "Bem-vindo ao SurfSense", + "welcome_description": "Crie seu primeiro espaço de pesquisa para começar a organizar seu conhecimento, conectar fontes e conversar com IA.", + "create_first_button": "Crie seu primeiro espaço de pesquisa" + }, + "userSettings": { + "title": "Configurações do usuário", + "description": "Gerencie suas configurações de conta e acesso à API", + "back_to_app": "Voltar ao app", + "profile_nav_label": "Perfil", + "profile_nav_description": "Gerencie seu nome e avatar", + "profile_title": "Perfil", + "profile_description": "Atualize suas informações pessoais", + "profile_avatar": "Foto do perfil", + "profile_display_name": "Nome de exibição", + "profile_display_name_hint": "É assim que seu nome aparece no aplicativo", + "profile_email": "E-mail", + "profile_save": "Salvar alterações", + "profile_saved": "Perfil atualizado com sucesso", + "profile_save_error": "Falha ao atualizar o perfil", + "api_key_nav_label": "Chave API", + "api_key_nav_description": "Gerencie seu token de acesso à API", + "api_key_title": "Chave API", + "api_key_description": "Use esta chave para autenticar solicitações da API", + "api_key_warning_title": "Mantenha em segredo", + "api_key_warning_description": "Sua chave API concede acesso total à sua conta. Nunca a compartilhe publicamente nem a inclua no controle de versão.", + "your_api_key": "Sua chave API", + "copied": "Copiado!", + "copy": "Copiar para a área de transferência", + "no_api_key": "Nenhuma chave API encontrada", + "usage_title": "Como usar", + "usage_description": "Inclua sua chave API no cabeçalho Authorization:" + }, + "dashboard": { + "title": "Painel", + "search_spaces": "Espaços de pesquisa", + "documents": "Documentos", + "connectors": "Conectores", + "settings": "Configurações", + "chat": "Chat", + "api_keys": "Chaves API", + "profile": "Perfil", + "loading_dashboard": "Carregando painel", + "loading_config": "Carregando configuração", + "config_error": "Erro de configuração", + "failed_load_llm_config": "Falha ao carregar sua configuração de LLM", + "error_loading_chats": "Erro ao carregar chats", + "loading_chat": "Carregando chat", + "loading_document": "Carregando documento", + "no_recent_chats": "Nenhum chat recente", + "error_loading_space": "Erro ao carregar o espaço de pesquisa", + "unknown_search_space": "Espaço de pesquisa desconhecido", + "delete_chat": "Excluir chat", + "delete_chat_confirm": "Tem certeza de que deseja excluir", + "delete_note": "Excluir nota", + "delete_note_confirm": "Tem certeza de que deseja excluir", + "action_cannot_undone": "Esta ação não pode ser desfeita.", + "deleting": "Excluindo", + "surfsense_dashboard": "Painel do SurfSense", + "welcome_message": "Bem-vindo ao seu painel do SurfSense.", + "your_search_spaces": "Seus espaços de pesquisa", + "shared": "Compartilhado", + "create_search_space": "Criar espaço de pesquisa", + "add_new_search_space": "Adicionar novo espaço de pesquisa", + "loading": "Carregando", + "may_take_moment": "Isso pode levar um momento", + "error": "Erro", + "something_wrong": "Algo deu errado", + "error_details": "Detalhes do erro", + "try_again": "Tentar novamente", + "go_home": "Ir para o início", + "delete_search_space": "Excluir espaço de pesquisa", + "delete_space_confirm": "Tem certeza de que deseja excluir \"{name}\"? Esta ação não pode ser desfeita. Todos os documentos e chats neste espaço de pesquisa serão excluídos permanentemente.", + "leave": "Sair", + "leave_title": "Sair do espaço de pesquisa", + "leave_confirm": "Tem certeza de que deseja sair de \"{name}\"? Você perderá acesso a todos os documentos e chats neste espaço de pesquisa.", + "leaving": "Saindo...", + "no_spaces_found": "Nenhum espaço de pesquisa encontrado", + "create_first_space": "Crie seu primeiro espaço de pesquisa para começar", + "created": "Criado" + }, + "navigation": { + "home": "Início", + "docs": "Documentação", + "pricing": "Preços", + "contact": "Contato", + "login": "Entrar", + "register": "Cadastrar", + "dashboard": "Painel", + "sign_in": "Entrar", + "book_a_call": "Agendar uma chamada" + }, + "nav_menu": { + "settings": "Configurações", + "platform": "Plataforma", + "chat": "Chat", + "manage_llms": "Gerenciar LLMs", + "sources": "Fontes", + "add_sources": "Adicionar fontes", + "documents": "Documentos", + "upload_documents": "Enviar documentos", + "add_webpages": "Adicionar páginas web", + "add_youtube": "Adicionar vídeos do YouTube", + "add_youtube_videos": "Adicionar vídeos do YouTube", + "manage_documents": "Gerenciar documentos", + "connectors": "Conectores", + "add_connector": "Adicionar conector", + "manage_connectors": "Gerenciar conectores", + "logs": "Logs", + "all_search_spaces": "Todos os espaços de pesquisa", + "team": "Equipe" + }, + "pricing": { + "title": "Preços do SurfSense", + "subtitle": "Escolha o que funciona para você", + "community_name": "COMUNIDADE", + "enterprise_name": "EMPRESA", + "forever": "para sempre", + "contact_us": "Fale conosco", + "feature_llms": "Suporta mais de 100 LLMs", + "feature_ollama": "Suporta configurações locais de Ollama ou vLLM", + "feature_embeddings": "Mais de 6000 modelos de embeddings", + "feature_files": "Mais de 50 extensões de arquivo suportadas.", + "feature_podcasts": "Suporte a podcasts com provedores TTS locais.", + "feature_sources": "Conecta com mais de 15 fontes externas.", + "feature_extension": "Extensão multi-navegador para páginas web dinâmicas incluindo conteúdo autenticado", + "upcoming_mindmaps": "Em breve: Mapas mentais combináveis", + "upcoming_notes": "Em breve: Gerenciamento de notas", + "community_desc": "Versão de código aberto com recursos poderosos", + "get_started": "Começar", + "everything_community": "Tudo da Comunidade", + "priority_support": "Suporte prioritário", + "access_controls": "Controles de acesso", + "collaboration": "Colaboração e recursos multiplayer", + "video_gen": "Geração de vídeo", + "advanced_security": "Recursos de segurança avançados", + "enterprise_desc": "Para grandes organizações com necessidades específicas", + "contact_sales": "Falar com vendas" + }, + "contact": { + "title": "Contato", + "subtitle": "Adoraríamos ouvir você.", + "we_are_here": "Estamos aqui", + "full_name": "Nome completo", + "email_address": "Endereço de e-mail", + "company": "Empresa", + "message": "Mensagem", + "optional": "opcional", + "name_placeholder": "João Silva", + "email_placeholder": "joao.silva@exemplo.com", + "company_placeholder": "Exemplo Ltda.", + "message_placeholder": "Digite sua mensagem aqui", + "submit": "Enviar", + "submitting": "Enviando...", + "name_required": "O nome é obrigatório", + "name_too_long": "O nome é muito longo", + "invalid_email": "Endereço de e-mail inválido", + "email_too_long": "O e-mail é muito longo", + "company_required": "A empresa é obrigatória", + "company_too_long": "O nome da empresa é muito longo", + "message_sent": "Mensagem enviada com sucesso!", + "we_will_contact": "Entraremos em contato o mais breve possível.", + "send_failed": "Falha ao enviar a mensagem", + "try_again_later": "Por favor, tente novamente mais tarde.", + "something_wrong": "Algo deu errado" + }, + "connectors": { + "title": "Conectores", + "subtitle": "Gerencie seus serviços conectados e fontes de dados.", + "add_connector": "Adicionar conector", + "your_connectors": "Seus conectores", + "view_manage": "Visualize e gerencie todos os seus serviços conectados.", + "no_connectors": "Nenhum conector encontrado", + "no_connectors_desc": "Você ainda não adicionou nenhum conector. Adicione um para melhorar suas capacidades de pesquisa.", + "add_first": "Adicione seu primeiro conector", + "name": "Nome", + "type": "Tipo", + "last_indexed": "Última indexação", + "periodic": "Periódico", + "actions": "Ações", + "never": "Nunca", + "not_indexable": "Não indexável", + "index_date_range": "Indexar com intervalo de datas", + "quick_index": "Indexação rápida", + "quick_index_auto": "Indexação rápida (intervalo automático)", + "delete_connector": "Excluir conector", + "delete_confirm": "Tem certeza de que deseja excluir este conector? Esta ação não pode ser desfeita.", + "select_date_range": "Selecionar intervalo de datas para indexação", + "select_date_range_desc": "Escolha as datas de início e fim para indexar o conteúdo. Deixe vazio para usar o intervalo padrão.", + "start_date": "Data de início", + "end_date": "Data de fim", + "pick_date": "Escolher data", + "clear_dates": "Limpar datas", + "last_30_days": "Últimos 30 dias", + "last_year": "Último ano", + "start_indexing": "Iniciar indexação", + "failed_load": "Falha ao carregar conectores", + "delete_success": "Conector excluído com sucesso", + "delete_failed": "Falha ao excluir conector", + "indexing_started": "Indexação do conteúdo do conector iniciada", + "indexing_failed": "Falha ao indexar conteúdo do conector" + }, + "documents": { + "title": "Documentos", + "subtitle": "Gerencie seus documentos e arquivos.", + "no_rows_selected": "Nenhuma linha selecionada", + "delete_success_count": "{count} documento(s) excluído(s) com sucesso", + "delete_partial_failed": "Alguns documentos não puderam ser excluídos", + "delete_success": "Documento excluído com sucesso", + "delete_error": "Erro ao excluir documentos", + "filter_by_title": "Filtrar por título...", + "bulk_delete": "Excluir selecionados", + "filter_types": "Filtrar tipos", + "columns": "Colunas", + "confirm_delete": "Confirmar exclusão", + "confirm_delete_desc": "Tem certeza de que deseja excluir {count} documento(s)? Esta ação não pode ser desfeita.", + "uploading": "Enviando", + "upload_success": "Documento enviado com sucesso", + "upload_failed": "Falha ao enviar documento", + "loading": "Carregando documentos", + "error_loading": "Erro ao carregar documentos", + "retry": "Tentar novamente", + "no_documents": "Nenhum documento encontrado", + "type": "Tipo", + "content_summary": "Resumo do conteúdo", + "view_full": "Ver resumo", + "filter_placeholder": "Filtrar por título...", + "rows_per_page": "Linhas por página", + "refresh": "Atualizar", + "upload_documents": "Enviar documentos", + "create_shared_note": "Criar nota compartilhada", + "processing_documents": "Processando documentos...", + "active_tasks_count": "{count} tarefa(s) ativa(s)" + }, + "add_connector": { + "title": "Conecte suas ferramentas", + "subtitle": "Integre com seus serviços favoritos para melhorar suas capacidades de pesquisa.", + "web_search": "Pesquisa web", + "messaging": "Mensagens", + "project_management": "Gerenciamento de projetos", + "documentation": "Documentação", + "development": "Desenvolvimento", + "databases": "Bancos de dados", + "productivity": "Produtividade", + "web_crawling": "Rastreamento web", + "connect": "Conectar", + "coming_soon": "Em breve", + "connected": "Conectado", + "manage": "Gerenciar", + "tavily_desc": "Pesquise na web usando a API do Tavily", + "searxng_desc": "Use sua própria instância SearxNG para resultados web.", + "linkup_desc": "Pesquise na web usando a API do Linkup", + "elasticsearch_desc": "Conecte-se ao Elasticsearch para indexar e pesquisar documentos, logs e métricas.", + "baidu_desc": "Pesquise na web chinesa usando a API Baidu AI Search", + "slack_desc": "Conecte-se ao seu workspace do Slack para acessar mensagens e canais.", + "teams_desc": "Conecte-se ao Microsoft Teams para acessar as conversas da sua equipe.", + "discord_desc": "Conecte-se a servidores Discord para acessar mensagens e canais.", + "linear_desc": "Conecte-se ao Linear para pesquisar issues, comentários e dados de projetos.", + "jira_desc": "Conecte-se ao Jira para pesquisar issues, tickets e dados de projetos.", + "clickup_desc": "Conecte-se ao ClickUp para pesquisar tarefas, comentários e dados de projetos.", + "notion_desc": "Conecte-se ao seu workspace do Notion para acessar páginas e bancos de dados.", + "github_desc": "Conecte um PAT do GitHub para indexar código e docs de repositórios acessíveis.", + "confluence_desc": "Conecte-se ao Confluence para pesquisar páginas, comentários e documentação.", + "bookstack_desc": "Conecte-se ao BookStack para pesquisar páginas wiki e documentação.", + "airtable_desc": "Conecte-se ao Airtable para pesquisar registros, tabelas e conteúdo de bancos de dados.", + "luma_desc": "Conecte-se ao Luma para pesquisar eventos, encontros e reuniões.", + "circleback_desc": "Receba notas de reuniões, transcrições e itens de ação do Circleback via webhook.", + "calendar_desc": "Conecte-se ao Google Calendar para pesquisar eventos, reuniões e agendas.", + "gmail_desc": "Conecte-se à sua conta do Gmail para pesquisar seus e-mails.", + "google_drive_desc": "Conecte-se ao Google Drive para pesquisar e indexar seus arquivos e documentos.", + "zoom_desc": "Conecte-se ao Zoom para acessar gravações e transcrições de reuniões.", + "webcrawler_desc": "Rastreie e indexe conteúdo de qualquer página web pública." + }, + "upload_documents": { + "title": "Enviar documentos", + "subtitle": "Envie seus arquivos para torná-los pesquisáveis e acessíveis através de conversas com IA.", + "file_size_limit": "Tamanho máximo do arquivo: 50 MB por arquivo.", + "upload_limits": "Limite de envio: {maxFiles} arquivos, {maxSizeMB} MB no total.", + "drop_files": "Solte os arquivos aqui", + "drag_drop": "Arraste e solte arquivos aqui", + "or_browse": "ou clique para navegar", + "browse_files": "Navegar arquivos", + "selected_files": "Arquivos selecionados ({count})", + "total_size": "Tamanho total", + "clear_all": "Limpar tudo", + "uploading_files": "Enviando arquivos", + "uploading": "Enviando", + "upload_button": "Enviar {count} {count, plural, one {arquivo} other {arquivos}}", + "upload_initiated": "Tarefa de envio iniciada", + "upload_initiated_desc": "O envio de arquivos foi iniciado", + "upload_error": "Erro no envio", + "upload_error_desc": "Erro ao enviar arquivos", + "supported_file_types": "Tipos de arquivo suportados", + "file_types_desc": "Estes tipos de arquivo são suportados com base na configuração atual do seu serviço ETL.", + "max_files_exceeded": "Limite de arquivos excedido", + "max_files_exceeded_desc": "Você pode enviar no máximo {max} arquivos de uma vez.", + "max_size_exceeded": "Limite de tamanho excedido", + "max_size_exceeded_desc": "O tamanho total dos arquivos não pode exceder {max} MB.", + "file_limit_reached": "Máximo de arquivos atingido", + "file_limit_reached_desc": "Remova alguns arquivos para adicionar mais (máximo {max} arquivos).", + "remaining_capacity": "{files} arquivos restantes • {sizeMB} MB disponíveis" + }, + "add_webpage": { + "title": "Adicionar páginas web para rastreamento", + "subtitle": "Insira URLs para rastrear e adicionar à sua coleção de documentos", + "label": "Insira URLs para rastrear", + "placeholder": "Insira uma URL e pressione Enter", + "hint": "Adicione múltiplas URLs pressionando Enter após cada uma", + "tips_title": "Dicas para rastreamento de URLs:", + "tip_1": "Insira URLs completas incluindo http:// ou https://", + "tip_2": "Certifique-se de que os sites permitem rastreamento", + "tip_3": "Páginas web públicas funcionam melhor", + "tip_4": "O rastreamento pode levar algum tempo dependendo do tamanho do site", + "cancel": "Cancelar", + "submit": "Enviar URLs para rastreamento", + "submitting": "Enviando...", + "error_no_url": "Por favor, adicione pelo menos uma URL", + "error_invalid_urls": "URLs inválidas detectadas: {urls}", + "crawling_toast": "Rastreamento de URL", + "crawling_toast_desc": "Iniciando processo de rastreamento de URL...", + "success_toast": "Rastreamento bem-sucedido", + "success_toast_desc": "As URLs foram enviadas para rastreamento", + "error_toast": "Erro no rastreamento", + "error_toast_desc": "Erro ao rastrear URLs", + "error_generic": "Ocorreu um erro ao rastrear URLs", + "invalid_url_toast": "URL inválida", + "invalid_url_toast_desc": "Por favor, insira uma URL válida", + "duplicate_url_toast": "URL duplicada", + "duplicate_url_toast_desc": "Esta URL já foi adicionada" + }, + "add_youtube": { + "title": "Adicionar vídeos do YouTube", + "subtitle": "Insira URLs de vídeos do YouTube para adicionar à sua coleção de documentos", + "label": "Insira URLs de vídeos do YouTube", + "placeholder": "Insira uma URL do YouTube e pressione Enter", + "hint": "Adicione múltiplas URLs do YouTube pressionando Enter após cada uma", + "tips_title": "Dicas para adicionar vídeos do YouTube:", + "tip_1": "Use URLs padrão do YouTube (youtube.com/watch?v= ou youtu.be/)", + "tip_2": "Certifique-se de que os vídeos sejam acessíveis publicamente", + "tip_3": "Formatos suportados: youtube.com/watch?v=VIDEO_ID ou youtu.be/VIDEO_ID", + "tip_4": "O processamento pode levar algum tempo dependendo da duração do vídeo", + "preview": "Visualizar", + "cancel": "Cancelar", + "submit": "Adicionar", + "processing": "Processando...", + "error_no_video": "Por favor, adicione pelo menos uma URL de vídeo do YouTube", + "error_invalid_urls": "URLs do YouTube inválidas detectadas: {urls}", + "processing_toast": "Processamento de vídeo do YouTube", + "processing_toast_desc": "Iniciando processamento de vídeo do YouTube...", + "success_toast": "Processamento bem-sucedido", + "success_toast_desc": "Os vídeos do YouTube foram enviados para processamento", + "error_toast": "Erro no processamento", + "error_toast_desc": "Erro ao processar vídeos do YouTube", + "error_generic": "Ocorreu um erro ao processar vídeos do YouTube", + "invalid_url_toast": "URL do YouTube inválida", + "invalid_url_toast_desc": "Por favor, insira uma URL válida de vídeo do YouTube", + "duplicate_url_toast": "URL duplicada", + "duplicate_url_toast_desc": "Este vídeo do YouTube já foi adicionado" + }, + "settings": { + "title": "Configurações", + "subtitle": "Gerencie suas configurações de LLM e atribuições de funções para este espaço de pesquisa.", + "back_to_dashboard": "Voltar ao painel", + "model_configs": "Configurações de modelos", + "models": "Modelos", + "llm_roles": "Funções de LLM", + "roles": "Funções", + "llm_role_management": "Gerenciamento de funções de LLM", + "llm_role_desc": "Atribua suas configurações de LLM a funções específicas para diferentes propósitos.", + "no_llm_configs_found": "Nenhuma configuração de LLM encontrada. Adicione pelo menos um provedor de LLM na aba Configurações de Modelos antes de atribuir funções.", + "select_llm_config": "Selecione uma configuração de LLM", + "long_context_llm": "LLM de contexto longo", + "fast_llm": "LLM rápido", + "strategic_llm": "LLM estratégico", + "long_context_desc": "Lida com resumos de documentos longos e perguntas complexas", + "long_context_examples": "Análise de documentos, síntese de pesquisa, perguntas complexas", + "large_context_window": "Janela de contexto ampla", + "deep_reasoning": "Raciocínio profundo", + "complex_analysis": "Análise complexa", + "fast_llm_desc": "Otimizado para respostas rápidas e interações em tempo real", + "fast_llm_examples": "Pesquisas rápidas, perguntas simples, respostas instantâneas", + "low_latency": "Baixa latência", + "quick_responses": "Respostas rápidas", + "real_time_chat": "Chat em tempo real", + "strategic_llm_desc": "Raciocínio avançado para planejamento e tomada de decisões estratégicas", + "strategic_llm_examples": "Planejamento de fluxos de trabalho, análise estratégica, resolução de problemas complexos", + "strategic_thinking": "Pensamento estratégico", + "long_term_planning": "Planejamento a longo prazo", + "complex_reasoning": "Raciocínio complexo", + "use_cases": "Casos de uso", + "assign_llm_config": "Atribuir configuração de LLM", + "unassigned": "Não atribuído", + "assigned": "Atribuído", + "model": "Modelo", + "base": "Base", + "all_roles_assigned": "Todas as funções estão atribuídas e prontas para uso! Sua configuração de LLM está completa.", + "save_changes": "Salvar alterações", + "saving": "Salvando", + "reset": "Redefinir", + "status": "Status", + "status_ready": "Pronto", + "status_setup": "Configuração", + "complete_role_assignments": "Complete todas as atribuições de funções para habilitar a funcionalidade completa. Cada função tem diferentes propósitos no seu fluxo de trabalho.", + "all_roles_saved": "Todas as funções atribuídas e salvas!", + "progress": "Progresso", + "roles_assigned_count": "{assigned} de {total} funções atribuídas" + }, + "logs": { + "title": "Logs de tarefas", + "subtitle": "Monitore e analise todos os logs de execução de tarefas", + "refresh": "Atualizar", + "delete_selected": "Excluir selecionados", + "confirm_title": "Tem certeza absoluta?", + "confirm_delete_desc": "Esta ação não pode ser desfeita. Isso excluirá permanentemente {count} log(s) selecionado(s).", + "cancel": "Cancelar", + "delete": "Excluir", + "level": "Nível", + "status": "Status", + "source": "Fonte", + "message": "Mensagem", + "created_at": "Criado em", + "actions": "Ações", + "system": "Sistema", + "filter_by_message": "Filtrar por mensagem...", + "filter_by": "Filtrar por", + "total_logs": "Total de logs", + "active_tasks": "Tarefas ativas", + "success_rate": "Taxa de sucesso", + "recent_failures": "Falhas recentes", + "last_hours": "Últimas {hours} horas", + "currently_running": "Em execução", + "successful": "bem-sucedido", + "need_attention": "Precisa de atenção", + "no_logs": "Nenhum log encontrado", + "loading": "Carregando logs...", + "error_loading": "Erro ao carregar logs", + "columns": "Colunas", + "failed_load_summary": "Falha ao carregar resumo", + "retry": "Tentar novamente", + "view": "Ver", + "toggle_columns": "Alternar colunas", + "rows_per_page": "Linhas por página", + "view_metadata": "Ver metadados", + "log_deleted_success": "Log excluído com sucesso", + "log_deleted_error": "Falha ao excluir log", + "confirm_delete_log_title": "Tem certeza?", + "confirm_delete_log_desc": "Esta ação não pode ser desfeita. Isso excluirá permanentemente a entrada do log.", + "deleting": "Excluindo" + }, + "onboard": { + "welcome_title": "Bem-vindo ao SurfSense", + "welcome_subtitle": "Vamos configurar suas configurações de LLM para começar", + "step_of": "Passo {current} de {total}", + "percent_complete": "{percent}% concluído", + "add_llm_provider": "Adicionar provedor de LLM", + "assign_llm_roles": "Atribuir funções de LLM", + "setup_llm_configuration": "Configurar LLM", + "configure_providers_and_assign_roles": "Adicione seus provedores de LLM e atribua-os a funções específicas", + "assign_llm_roles_title": "Atribuir funções de LLM", + "complete_role_assignment": "Atribua suas configurações de LLM a funções específicas para continuar", + "setup_complete": "Configuração concluída", + "configure_first_provider": "Configure seu primeiro provedor de modelos", + "assign_specific_roles": "Atribua funções específicas às suas configurações de LLM", + "all_set": "Tudo pronto para começar a usar o SurfSense!", + "loading_config": "Carregando sua configuração...", + "previous": "Anterior", + "next": "Próximo", + "complete_setup": "Concluir configuração", + "add_provider_instruction": "Adicione pelo menos um provedor de LLM para continuar. Você pode configurar múltiplos provedores e escolher funções específicas para cada um no próximo passo.", + "your_llm_configs": "Suas configurações de LLM", + "model": "Modelo", + "language": "Idioma", + "base": "Base", + "add_provider_title": "Adicionar provedor de LLM", + "add_provider_subtitle": "Configure seu primeiro provedor de modelos para começar", + "add_provider_button": "Adicionar provedor", + "add_new_llm_provider": "Adicionar novo provedor de LLM", + "configure_new_provider": "Configure um novo provedor de modelo de linguagem para seu assistente de IA", + "config_name": "Nome da configuração", + "config_name_required": "Nome da configuração *", + "config_name_placeholder": "ex., Meu OpenAI GPT-4", + "provider": "Provedor", + "provider_required": "Provedor *", + "provider_placeholder": "Selecione um provedor", + "language_optional": "Idioma (opcional)", + "language_placeholder": "Selecione o idioma", + "custom_provider_name": "Nome do provedor personalizado *", + "custom_provider_placeholder": "ex., meu-provedor-personalizado", + "model_name_required": "Nome do modelo *", + "model_name_placeholder": "ex., gpt-4", + "examples": "Exemplos", + "api_key_required": "Chave API *", + "api_key_placeholder": "Sua chave API", + "api_base_optional": "URL base da API (opcional)", + "api_base_placeholder": "ex., https://api.openai.com/v1", + "adding": "Adicionando...", + "add_provider": "Adicionar provedor", + "cancel": "Cancelar", + "assign_roles_instruction": "Atribua suas configurações de LLM a funções específicas. Cada função tem diferentes propósitos no seu fluxo de trabalho.", + "no_llm_configs_found": "Nenhuma configuração de LLM encontrada", + "add_provider_before_roles": "Adicione pelo menos um provedor de LLM no passo anterior antes de atribuir funções.", + "long_context_llm_title": "LLM de contexto longo", + "long_context_llm_desc": "Lida com resumos de documentos longos e perguntas complexas", + "long_context_llm_examples": "Análise de documentos, síntese de pesquisa, perguntas complexas", + "fast_llm_title": "LLM rápido", + "fast_llm_desc": "Otimizado para respostas rápidas e interações em tempo real", + "fast_llm_examples": "Pesquisas rápidas, perguntas simples, respostas instantâneas", + "strategic_llm_title": "LLM estratégico", + "strategic_llm_desc": "Raciocínio avançado para planejamento e tomada de decisões estratégicas", + "strategic_llm_examples": "Planejamento de fluxos de trabalho, análise estratégica, resolução de problemas complexos", + "use_cases": "Casos de uso", + "assign_llm_config": "Atribuir configuração de LLM", + "select_llm_config": "Selecione uma configuração de LLM", + "assigned": "Atribuído", + "all_roles_assigned_saved": "Todas as funções atribuídas e salvas!", + "progress": "Progresso", + "roles_assigned": "{assigned} de {total} funções atribuídas", + "global_configs": "Configurações globais", + "your_configs": "Suas configurações" + }, + "model_config": { + "title": "Configurações de modelos", + "subtitle": "Gerencie as configurações dos seus provedores de LLM e configurações de API.", + "refresh": "Atualizar", + "loading": "Carregando configurações...", + "total_configs": "Total de configurações", + "unique_providers": "Provedores únicos", + "system_status": "Status do sistema", + "active": "Ativo", + "your_configs": "Suas configurações", + "manage_configs": "Gerencie e configure seus provedores de LLM", + "add_config": "Adicionar configuração", + "no_configs": "Nenhuma configuração ainda", + "no_configs_desc": "Adicione suas próprias configurações de provedor de LLM.", + "add_first_config": "Adicionar primeira configuração", + "created": "Criado" + }, + "breadcrumb": { + "dashboard": "Painel", + "search_space": "Espaço de pesquisa", + "chat": "Chat", + "documents": "Documentos", + "connectors": "Conectores", + "editor": "Editor", + "logs": "Logs", + "settings": "Configurações", + "upload_documents": "Enviar documentos", + "add_youtube": "Adicionar vídeos do YouTube", + "add_webpages": "Adicionar páginas web", + "add_connector": "Adicionar conector", + "manage_connectors": "Gerenciar conectores", + "edit_connector": "Editar conector", + "manage": "Gerenciar" + }, + "sidebar": { + "chats": "Chats privados", + "shared_chats": "Chats compartilhados", + "search_chats": "Pesquisar chats", + "no_chats_found": "Nenhum chat encontrado", + "no_shared_chats": "Nenhum chat compartilhado", + "view_all_shared_chats": "Ver todos os chats compartilhados", + "view_all_private_chats": "Ver todos os chats privados", + "no_chats": "Nenhum chat ainda", + "start_new_chat_hint": "Iniciar um novo chat", + "error_loading_chats": "Erro ao carregar chats", + "chat_deleted": "Chat excluído com sucesso", + "error_deleting_chat": "Falha ao excluir chat", + "delete": "Excluir", + "try_different_search": "Tente um termo de pesquisa diferente", + "updated": "Atualizado", + "more_options": "Mais opções", + "clear_search": "Limpar pesquisa", + "archive": "Arquivar", + "unarchive": "Restaurar", + "chat_archived": "Chat arquivado", + "chat_unarchived": "Chat restaurado", + "chat_renamed": "Chat renomeado", + "error_renaming_chat": "Falha ao renomear chat", + "rename": "Renomear", + "rename_chat": "Renomear chat", + "rename_chat_description": "Insira um novo nome para esta conversa.", + "chat_title_placeholder": "Título do chat", + "renaming": "Renomeando...", + "no_archived_chats": "Nenhum chat arquivado", + "error_archiving_chat": "Falha ao arquivar chat", + "new_chat": "Novo chat", + "select_search_space": "Selecionar espaço de pesquisa", + "manage_members": "Gerenciar membros", + "search_space_settings": "Configurações do espaço de pesquisa", + "logs": "Logs", + "see_all_search_spaces": "Ver todos os espaços de pesquisa", + "expand_sidebar": "Expandir barra lateral", + "collapse_sidebar": "Recolher barra lateral", + "user_settings": "Configurações do usuário", + "language": "Idioma", + "theme": "Tema", + "light": "Claro", + "dark": "Escuro", + "system": "Sistema", + "logout": "Sair", + "loggingOut": "Saindo...", + "inbox": "Caixa de entrada", + "search_inbox": "Pesquisar caixa de entrada", + "mark_all_read": "Marcar tudo como lido", + "mark_as_read": "Marcar como lido", + "mentions": "Menções", + "comments": "Comentários", + "status": "Status", + "no_results_found": "Nenhum resultado encontrado", + "no_mentions": "Sem menções", + "no_mentions_hint": "Você verá as menções de outros aqui", + "no_comments": "Sem comentários", + "no_comments_hint": "Você verá menções e respostas aqui", + "no_status_updates": "Sem atualizações de status", + "no_status_updates_hint": "Atualizações de documentos e conectores aparecerão aqui", + "filter": "Filtrar", + "all": "Tudo", + "unread": "Não lido", + "connectors": "Conectores", + "all_connectors": "Todos os conectores", + "close": "Fechar" + }, + "errors": { + "something_went_wrong": "Algo deu errado", + "try_again": "Por favor, tente novamente", + "not_found": "Não encontrado", + "unauthorized": "Não autorizado", + "forbidden": "Proibido", + "server_error": "Erro do servidor", + "network_error": "Erro de rede" + }, + "searchSpaceSettings": { + "title": "Configurações do espaço de pesquisa", + "back_to_app": "Voltar ao app", + "nav_general": "Geral", + "nav_general_desc": "Nome, descrição e informações básicas", + "nav_agent_configs": "Configurações do agente", + "nav_agent_configs_desc": "Modelos LLM com prompts e citações", + "nav_role_assignments": "Atribuições de funções", + "nav_role_assignments_desc": "Atribuir configurações a funções do agente", + "nav_image_models": "Modelos de imagem", + "nav_image_models_desc": "Configurar modelos de geração de imagens", + "nav_system_instructions": "Instruções do sistema", + "nav_system_instructions_desc": "Instruções de IA em nível do espaço de pesquisa", + "nav_public_links": "Links de chat públicos", + "nav_public_links_desc": "Gerenciar links de chat compartilhados publicamente", + "general_name_label": "Nome", + "general_name_placeholder": "Insira o nome do espaço de pesquisa", + "general_name_description": "Um nome único para seu espaço de pesquisa.", + "general_description_label": "Descrição", + "general_description_placeholder": "Insira a descrição do espaço de pesquisa", + "general_description_description": "Uma breve descrição de para que este espaço de pesquisa será usado.", + "general_reset": "Redefinir alterações", + "general_save": "Salvar alterações", + "general_saving": "Salvando", + "general_unsaved_changes": "Você tem alterações não salvas. Clique em \"Salvar alterações\" para aplicá-las." + }, + "homepage": { + "hero_title_part1": "O espaço de trabalho com IA", + "hero_title_part2": "feito para equipes", + "hero_description": "Conecte qualquer LLM às suas fontes de conhecimento internas e converse com ele em tempo real junto com sua equipe.", + "cta_start_trial": "Comece gratuitamente", + "cta_explore": "Explorar", + "integrations_title": "Integrações", + "integrations_subtitle": "Integre com as ferramentas mais importantes da sua equipe", + "features_title": "O hub de conhecimento da sua equipe com IA", + "features_subtitle": "Recursos poderosos projetados para melhorar a colaboração, aumentar a produtividade e otimizar seu fluxo de trabalho.", + "feature_workflow_title": "Fluxo de trabalho otimizado", + "feature_workflow_desc": "Centralize todo o seu conhecimento e recursos em um espaço de trabalho inteligente. Encontre o que precisa instantaneamente e acelere a tomada de decisões.", + "feature_collaboration_title": "Colaboração perfeita", + "feature_collaboration_desc": "Trabalhe junto com sua equipe sem esforço com ferramentas de colaboração em tempo real que mantêm todos alinhados.", + "feature_customizable_title": "Totalmente personalizável", + "feature_customizable_desc": "Escolha entre mais de 100 LLMs líderes e chame qualquer modelo sob demanda sem problemas.", + "cta_transform": "Transforme como sua equipe", + "cta_transform_bold": "descobre e colabora", + "cta_unite_start": "Unifique o", + "cta_unite_knowledge": "conhecimento da sua equipe", + "cta_unite_middle": "em um espaço colaborativo com", + "cta_unite_search": "pesquisa inteligente", + "cta_talk_to_us": "Fale conosco", + "features": { + "find_ask_act": { + "title": "Encontre, pergunte, aja", + "description": "Obtenha informações instantâneas, atualizações detalhadas e respostas com citações do conhecimento da empresa e pessoal." + }, + "real_time_collab": { + "title": "Trabalhe junto em tempo real", + "description": "Transforme os documentos da sua empresa em espaços multiplayer com edições ao vivo, conteúdo sincronizado e presença." + }, + "beyond_text": { + "title": "Colabore além do texto", + "description": "Crie podcasts e multimídia que sua equipe pode comentar, compartilhar e aprimorar juntos." + }, + "context_counts": { + "title": "Contexto onde importa", + "description": "Adicione comentários diretamente aos seus chats e documentos para feedback claro e no momento." + }, + "citation_illustration_title": "Ilustração do recurso de citação mostrando referência de fonte clicável", + "referenced_chunk": "Trecho referenciado", + "collab_illustration_label": "Ilustração de colaboração em tempo real em um editor de texto.", + "real_time": "Tempo real", + "collab_part1": "colabo", + "collab_part2": "raç", + "collab_part3": "ão", + "annotation_illustration_label": "Ilustração de um editor de texto com comentários de anotação.", + "add_context_with": "Adicione contexto com", + "comments": "comentários", + "example_comment": "Vamos discutir isso amanhã!" + } + }, + "public_chat": { + "not_found_title": "Este chat foi excluído.", + "click_here": "Clique aqui", + "sign_in_prompt": "para entrar no SurfSense e começar o seu." + } +}