// ==UserScript== // @name 🌳ChatTree🌳 // @name:zh-CN 🌳ChatTree🌳 // @namespace https://czz9.top // @version 2023.10.4 // @description A intuitive, flexible, and user-friendly tool for real-time updates and customizing conversation trees, with support for dragging, zooming, searching, and managing, making interactions with ChatGPT more convenient and personalized. // @description:ar أداة بديهية ومرنة وودية للمستخدم، تحديث في الوقت الحقيقي وتخصيص شجرة الدردشة، تدعم السحب والإسقاط، التكبير/التصغير، البحث والإدارة، مما يجعل التفاعل مع ChatGPT أسهل وأكثر تخصصًا. // @description:bg Интуитивен, гъвкав и потребителски приятелски инструмент, реално време обновяване и персонализиране на диалоговото дърво, поддържа плъзгане и пускане, мащабиране, търсене и управление, което прави взаимодействието с ChatGPT по-лесно и персонализирано. // @description:cs Intuitivní, flexibilní a uživatelsky přívětivý nástroj, aktualizace v reálném čase a přizpůsobení stromu dialogu, podpora táhnutí a přetažení, zoom, vyhledávání a správa, činí interakci s ChatGPT snadnější a personalizovanější. // @description:da En intuitiv, fleksibel og brugervenlig værktøj, realtidsopdatering og tilpasning af dialogtræ, understøtter træk og slip, zoom, søgning og styring, gør interaktion med ChatGPT lettere og mere personlig. // @description:de Ein intuitives, flexibles und benutzerfreundliches Werkzeug, Echtzeit-Aktualisierung und Anpassung des Dialogbaums, unterstützt Drag & Drop, Zoom, Suche und Verwaltung, macht die Interaktion mit ChatGPT einfacher und individueller. // @description:el Ένα εύχρηστο, ευέλικτο και φιλικό προς τον χρήστη εργαλείο, ενημέρωση σε πραγματικό χρόνο και προσαρμογή του δέντρου διαλόγου, υποστηρίζει τη μεταφορά και απόθεση, το ζουμ, την αναζήτηση και τη διαχείριση, καθιστώντας την αλληλεπίδραση με το ChatGPT πιο εύκολη και προσαρμοσμένη. // @description:en An intuitive, flexible, and user-friendly tool, real-time updating and customization of the dialog tree, supports drag-and-drop, zoom, search, and management, making interaction with ChatGPT more convenient and personalized. // @description:eo Intuitiva, fleksebla kaj uzantamika ilo, ĝisdatigas kaj proprigas la dialogan arbon reale, subtenas ŝovmeti, zoomi, serĉi kaj administri, igante la interagon kun ChatGPT pli oportuna kaj personeca. // @description:es Una herramienta intuitiva, flexible y amigable para el usuario, actualización en tiempo real y personalización del árbol de diálogo, soporta arrastrar y soltar, zoom, búsqueda y gestión, haciendo que la interacción con ChatGPT sea más conveniente y personalizada. // @description:fi Intuitiivinen, joustava ja käyttäjäystävällinen työkalu, dialogipuun reaaliaikainen päivitys ja mukauttaminen, tukee vetämistä ja pudottamista, zoomausta, hakua ja hallintaa, tekee vuorovaikutuksesta ChatGPT: n kanssa kätevämmän ja henkilökohtaisemman. // @description:fr Un outil intuitif, flexible et convivial, mise à jour en temps réel et personnalisation de l'arbre de dialogue, prend en charge le glisser-déposer, le zoom, la recherche et la gestion, rendant l'interaction avec ChatGPT plus pratique et personnalisée. // @description:fr-CA Un outil intuitif, flexible et convivial, mise à jour en temps réel et personnalisation de l'arbre de dialogue, prend en charge le glisser-déposer, le zoom, la recherche et la gestion, rendant l'interaction avec ChatGPT plus pratique et personnalisée. // @description:he כלי אינטואיטיבי, גמיש וידידותי למשתמש, עדכון בזמן אמת והתאמה אישית של עץ הדיאלוג, תומך בגרירה ושחרור, זום, חיפוש וניהול, והופך את האינטראקציה עם ChatGPT לנוחה ומותאמת אישית יותר. // @description:hu Egy intuitív, rugalmas és felhasználóbarát eszköz, valós idejű frissítés és a párbeszéd fa testreszabása, támogatja a húzást és az ejtést, a nagyítást, a keresést és a kezelést, megkönnyítve az interakciót a ChatGPT-vel és személyre szabottabbá téve azt. // @description:id Alat intuitif, fleksibel, dan ramah pengguna, pembaruan real-time dan penyesuaian pohon dialog, mendukung seret dan lepas, zoom, pencarian, dan manajemen, membuat interaksi dengan ChatGPT lebih nyaman dan personal. // @description:it Uno strumento intuitivo, flessibile e user-friendly, aggiornamento in tempo reale e personalizzazione dell'albero dei dialoghi, supporta il drag-and-drop, lo zoom, la ricerca e la gestione, rendendo l'interazione con ChatGPT più conveniente e personalizzata. // @description:ja 直感的で柔軟でユーザーフレンドリーなツール、ダイアログツリーのリアルタイム更新とカスタマイズ、ドラッグアンドドロップ、ズーム、検索、管理をサポートし、ChatGPTとのインタラクションをより便利でパーソナライズされたものにします。 // @description:ka ინტუიციური, გადაწყვეტი და მომხმარებლებთან მეგობრიანი ხელსაწყო, დიალოგების ხეების განახლება რეალურ დროში და პერსონალიზაცია, რეჟიმების ჩამოყალიბების, გადიდების, ძიებისა და მართვის მხარდაჭერა, რაც გახდის ChatGPT-თან ინტერაქციას უფრო კომფორტულ და პერსონალურ. // @description:ko 직관적이고 유연하며 사용자 친화적인 도구, 실시간 업데이트 및 대화 트리 사용자 정의, 드래그 앤 드롭, 줌, 검색 및 관리 지원, ChatGPT와의 상호 작용을 더 편리하고 개인화된 경험으로 만듭니다. // @description:nb Et intuitivt, fleksibelt og brukervennlig verktøy, sanntidsoppdatering og tilpasning av dialogtreet, støtter dra og slipp, zoom, søk og styring, noe som gjør interaksjon med ChatGPT mer praktisk og personlig. // @description:nl Een intuïtief, flexibel en gebruiksvriendelijk hulpmiddel, real-time bijwerken en aanpassen van de dialoogboom, ondersteunt slepen en neerzetten, zoomen, zoeken en beheren, waardoor interactie met ChatGPT handiger en gepersonaliseerd wordt. // @description:pl Intuicyjne, elastyczne i przyjazne użytkownikowi narzędzie, aktualizacja w czasie rzeczywistym i dostosowywanie drzewa dialogowego, obsługuje przeciąganie i upuszczanie, powiększanie, wyszukiwanie i zarządzanie, co sprawia, że interakcja z ChatGPT jest bardziej wygodna i spersonalizowana. // @description:pt-PT Uma ferramenta intuitiva, flexível e amigável para o usuário, com atualização em tempo real e personalização da árvore de diálogo, suporta arrastar e soltar, zoom, pesquisa e gestão, tornando a interação com o ChatGPT mais conveniente e personalizada. // @description:pt-BR Uma ferramenta intuitiva, flexível e amigável ao usuário, atualização em tempo real e personalização da árvore de diálogo, suporta arrastar e soltar, zoom, pesquisa e gerenciamento, tornando a interação com o ChatGPT mais conveniente e personalizada. // @description:ro Un instrument intuitiv, flexibil și prietenos pentru utilizator, actualizare în timp real și personalizarea arborelui de dialog, suportă drag-and-drop, zoom, căutare și management, făcând interacțiunea cu ChatGPT mai convenabilă și personalizată. // @description:ru Интуитивный, гибкий и удобный инструмент, обновление в реальном времени и настройка дерева диалога, поддерживает перетаскивание, масштабирование, поиск и управление, делая взаимодействие с ChatGPT более удобным и персонализированным. // @description:sk Intuitívny, flexibilný a užívateľsky príjemný nástroj, aktualizácia v reálnom čase a prispôsobenie stromu dialógov, podporuje pretiahnutie a pustenie, priblíženie, vyhľadávanie a správu, čo uľahčuje interakciu s ChatGPT a personalizuje ju. // @description:sr Интуитиван, флексибилан и кориснички пријатан алат, ажурирање у реалном времену и прилагођавање дијалога, подржава превлачење, зумирање, претрагу и управљање, олакшавајући интеракцију са ChatGPT и персонализујући је. // @description:sv Ett intuitivt, flexibelt och användarvänligt verktyg, uppdatering i realtid och anpassning av dialogträdet, stöder dra och släpp, zoomning, sökning och hantering, vilket gör interaktionen med ChatGPT mer bekväm och personlig. // @description:th เครื่องมือที่ใช้งานง่าย ยืดหยุ่น และเป็นมิตรกับผู้ใช้ การอัปเดตแบบเรียลไทม์และการปรับแต่งต้นไม้ของการสนทนา รองรับการลากและวาง การซูม การค้นหาและการจัดการ ทำให้การโต้ตอบกับ ChatGPT สะดวกและส่วนบุคคลขึ้น // @description:tr Kullanıcı dostu, esnek ve kullanıcı dostu bir araç, dialog ağacının gerçek zamanlı güncellemesi ve özelleştirmesi, sürükle ve bırak, yakınlaştırma, arama ve yönetimi destekler, ChatGPT ile etkileşimi daha uygun ve kişiselleştirilmiş hale getirir. // @description:uk Інтуїтивний, гнучкий та зручний для користувача інструмент, оновлення в реальному часі та налаштування діалогового дерева, підтримує перетягування, масштабування, пошук та керування, спрощуючи взаємодію з ChatGPT та роблячи її більш індивідуалізованою. // @description:ug ئىنتۇئىتىۋ، يۇمشاق ۋە ئىشلىتكۈچى دوستىي قورال، سۆھبەت تارىخچىسىنى ۋاقتى ۋاقتىلا يېڭىلاش ۋە ئۆزگەرتىش، تارتىپلاش، چوڭايتىش، ئىزدەش ۋە باشقۇرۇشنى قوللايدۇ، ChatGPT بىلەن ئاراملىشىشنى يەنە قولاي ۋە شەخسىيلاشتۇرىدۇ. // @description:vi Một công cụ trực quan, linh hoạt và thân thiện với người dùng, cập nhật theo thời gian thực và tùy chỉnh cây hội thoại, hỗ trợ kéo và thả, zoom, tìm kiếm và quản lý, làm cho tương tác với ChatGPT thuận tiện và cá nhân hóa hơn. // @description:zh-CN 一款直观、灵活和用户友好的工具,实时更新和自定义对话树,支持拖拽、缩放、搜索和管理,让与ChatGPT的互动更加便捷和个性化。 // @description:zh-TW 一款直觀、靈活和使用者友善的工具,即時更新和自定義對話樹,支援拖放、縮放、搜尋和管理,讓與ChatGPT的互動更加便利和個人化。 // @author cuizhenzhi // @match *://chat.openai.com/* // @grant GM_addStyle // @grant GM_getResourceText // @require https://cdnjs.cloudflare.com/ajax/libs/d3/5.16.0/d3.min.js // @require https://cdn.jsdelivr.net/npm/animejs@3.2.1/lib/anime.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/interact.js/1.10.11/interact.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/2.0.8/clipboard.min.js // @supportURL https://docs.google.com/forms/d/e/1FAIpQLSetbHqiS1GBM6bG0QaaKy9cN31jKXK76BcYCW8_wkRNH7I5kQ/viewform // @license GPL-2.0-only // @icon data:image/svg+xml;utf8, // @downloadURL none // ==/UserScript== (function () { "use strict"; const isDevelopmentMode = false; function log(...messages) { if (isDevelopmentMode) { console.log(...messages); } } function error(...messages) { console.error(...messages); } GM_addStyle(` @keyframes textBlink { 0%, 100% { color: black; } 50% { color: white; } } .blinkText { animation: textBlink 1s ease-in-out infinite; } @keyframes highlight { 0% { background-color: initial; } 50% { background-color: #ffffff; } 100% { background-color: initial; } } .highlight { animation: highlight 2s ease-in-out infinite; } @keyframes highlightt { 0% { background-color: initial; } 50% { background-color: #000000; } 100% { background-color: initial; } } .highlightt { animation: highlightt 2s ease-in-out infinite; } .close-button { margin-left: 5px; color: red; cursor: pointer; } .suggestions-container { position: absolute; left: 40px; width: 270px; top: 100%; /* Place it below the search box */ max-height: 150px; /* Adjust as per your preference */ overflow-y: auto; /* Add scrollbar if content is too much */ border: 1px solid #ccc; background-color: white; z-index: 99; /* Make it appear on top of other elements */ } .suggestion-item { padding: 10px; cursor: pointer; } .suggestion-item:hover { background-color: #eee; } .node-menu { display: none; position: absolute; border: 1px solid black; background-color: white; } #contentDiv { box-sizing: border-box; } /* Cursor styles */ .node { cursor: pointer; } .node circle { fill: #e5e5e5; } .node circle.chatgpt { } .node circle.用户 { fill: #1E90FF; } .node.descendant-dragging circle { fill: #b0e0e6 !important; } .node.selectedNode circle { fill: red !important; } .link.highlighted { /*stroke: yellow;*/ stroke: #808080; stroke-width: 4px; } .link.descendant-highlighted { stroke: #d3d3d3; /* 选择你想要的颜色 */ stroke-width: 4px; } .content-text { white-space: pre-line; } /* Menu styles */ .menu { opacity: 0; transition: opacity 300ms, transform 300ms; transform: translateX(100%); /* Start from the right */ border: none; /* Remove border */ } .menu.show { opacity: 1; transform: translateX(0); /* Move to its original position */ } #commentForm { width: 300px; padding: 20px; border: 1px solid #ccc; border-radius: 5px; box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2); } #commentForm label, #commentForm textarea, #commentForm button { display: block; width: 100%; margin-bottom: 10px; } #commentForm textarea { resize: none; /* 禁止调整大小 */ } .commentHoverEffect { transition: all 0.3s ease-in-out; } .commentHoverEffect:hover { font-weight: bold; text-shadow: 2px 2px 4px rgba(0,0,0,0.5); } /*这是显示对话内容的注释样式*/ .comment-text { color: #ff5555; font-style: italic; margin-right: 10px; display: block; font-weight: bold; border-bottom: 2px dashed #ff5555; } /* SVG background */ #thumbnailSvg { /*background-color: rgba(128, 128, 128, 0.4); !* Gray with 0.4 opacity *!*/ /*background-image: linear-gradient(to top, #fad0c4 0%, #ffd1ff 100%);*/ background-image: linear-gradient(to top, rgba(250, 208, 196, 1) 0%, rgba(255, 209, 255, 0.9) 100%); /*background-image: linear-gradient(to top, rgba(220,220,220, 1) 0%, rgba(220,220,220, 1) 100%);*/ } #mainSvg { /*background-color: rgba(128, 128, 128, 0.4); !* Gray with 0.4 opacity *!*/ /*background-image: linear-gradient(to top, #fad0c4 0%, #ffd1ff 100%);*/ /*background-image: linear-gradient(to top, rgba(220,220,220, 0.2) 0%, rgba(220,220,220, 0.2) 100%);*/ background-image: linear-gradient(to top, rgba(250, 208, 196, 0.2) 0%, rgba(255, 209, 255, 0.2) 100%); } #search-container { top: 20px; left: 20px; display: flex; align-items: center; position: fixed; width: 50px; height: 40px; color: black; /*overflow: hidden;*/ background: transparent; /*flex-wrap: wrap;*/ /*z-index: 10000;*/ } #search-icon { width: 40px; height: 40px; cursor: pointer; display: flex; align-items: center; justify-content: center; font-size: 24px; /* adjust as needed */ background: transparent; /*background-color: #f1f1f1;*/ } #search-box { margin-top: 10px; width: 300px; height: 40px; /*background-color: #f1f1f1;*/ border: none; padding: 0 10px; outline: none; background: transparent; opacity: 0; pointer-events: none; border-radius: 6px; } #search-btn { padding: 5px 15px; margin-left: 10px; display: none; } #search-history { position: absolute; top: 50px; left: 0; /*display: none;*/ opacity: 0; /* 设置为 0 使其默认隐藏 */ /*display: ;*/ display: flex; flex-direction: row; /* 横向排列 */ flex-wrap: wrap; /* 当空间不足时换行 */ width: 0px; min-height: 0px; /* instead of height: 0px; */ align-content: flex-start; height: 20px; max-height: 200px; /*align-items: center; !* 确保每行的内容垂直居中对齐 *!*/ overflow-y: scroll; overflow-x: hidden; padding: 10px; /* 为了避免内容紧贴边缘,给予一些内边距 */ /*z-index: 10001;*/ /*border-radius: 6px;*/ } #search-results-count { box-sizing: border-box; line-height: 26px; /* 重置行高 */ margin: 0; padding: 3px 6px; display: flex; justify-content: center; /* 水平居中 */ align-items: center; /* 垂直居中 */ } .history-item { display: flex; align-items: center; width: auto; /* 根据内容自动调整宽度 */ max-width: 150px; /* 设置最大宽度 */ max-height: 30px; overflow: hidden; background-color: #f5f5f5; border-radius: 15px; padding: 5px 10px; margin-top: 10px; margin-right: 10px; /* 每个 history-item 之间的间距 */ /*gap: 10px;*/ } .history-text { /*max-width: 100px; !* 设置最大宽度 *!*/ flex-shrink: 1; min-width: 0; white-space: nowrap; /* 防止文本换行 */ overflow: hidden; text-overflow: ellipsis; /* 使用省略号 (...) 表示被裁切的文本 */ /*padding: 5px 10px;*/ } .history-delete { cursor: pointer; padding: 5px; border-radius: 50%; transition: background-color 0.3s; margin-left: auto; /* 这会将按钮推到其父元素的右边 */ } .history-delete:hover { background-color: rgba(200, 0, 0, 0.1); } #settingsDiv, .actionDiv { width: 40px; height: 40px; display: flex; align-items: center; justify-content: center; position: fixed; z-index: 1000; background-color: rgba(255, 255, 255, 0.8); border-radius: 50%; /* 让div成为圆形 */ /*box-shadow: 0px 0px 10px rgba(0, 0, 0, 0.5);*/ box-shadow: none; transition: background-color 0.3s; /* 平滑过渡效果 */ user-select: none; } @keyframes spin { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } #settingsDiv { animation: spin 4s linear infinite; } #settingsDiv { right: 10px; bottom: 10px; color: rebeccapurple; /* 或你想要的任何颜色 */ cursor: pointer; display: flex; justify-content: center; /* 水平居中 */ align-items: center; /* 垂直居中 */ } .actionDiv { display: none; /* 默认隐藏 */ right: 10px; /* 你可以根据需要调整这些值来确定div的位置 */ cursor: pointer; color: deepskyblue; /* 或你想要的任何颜色 */ font-size: 1.5em; } #plusDiv { bottom: 110px; } #minusDiv { bottom: 60px; } #thumbNailDiv { bottom: 160px; } #refreshTree { bottom: 210px; } #undoDiv { bottom: 260px; } #redoDiv { bottom: 310px; } #deleteDiv { bottom: 360px; } #feedbackDiv { bottom: 410px; } #settingsDiv:hover, .actionDiv:hover { background-color: rgba(200, 200, 255, 0.9); /* 悬停时的背景色 */ } `); const getLang = function () { let lang = `{ "ar": { "chatTreeRunning": "🥳🌳ChatTree🌳في التشغيل!🎉", "updateCurrentConversationTree": "🌈 تحديث شجرة المحادثة الحالية 🌈", "adjustBackgroundColorAndOpacity": "🎨 تعديل لون الخلفية والشفافية 🎨", "toggleConversationTree": "🌳 عرض/إخفاء شجرة المحادثة 🌳", "noDatabaseAndCreationFailed": "لا يوجد قاعدة بيانات، ولم يتم الإنشاء بنجاح! الخروج من البرنامج النصي!", "mismatchedLink": "الرابط غير متطابق، يرجى تحديث الصفحة!", "startUpdatingConversationTree": "بدء تحديث شجرة المحادثة", "selectedItem": "لقد اخترت {item}", "successSavingChanges": "تم حفظ التغييرات بنجاح!", "codeCopiedToClipboard": "تم نسخ الكود إلى الحافظة!", "contentCopied": "تم نسخ المحتوى!", "emptyCommentPrompt": "التعليق فارغ. هل تريد ضبط التعليق على \\"فارغ\\"؟", "confirmDeleteLinkData": "تم التحقق من الرابط كـ {item}! هل تريد حذف بيانات هذا الرابط؟ سيتم حذف جميع محتوى المحادثة والتعليقات!", "confirmCurrentURL": "تم التحقق من الرابط كـ {item}! هل أنت متأكد؟", "commentSetToEmpty": "تم تعيين التعليق على \\"فارغ\\"", "enterCommentFirst": "الرجاء إدخال التعليق أولا", "commentSaved": "تم حفظ التعليق", "conversationDataDeleted": "تم حذف بيانات المحادثة بنجاح", "executeSearchWithQuery": "تنفيذ البحث: {item}", "searchPlaceholder": "أدخل كلمات البحث...", "searchButton": "بحث", "searchInContent": "في محتوى المحادثة", "searchInComments": "في التعليقات", "searchInBoth": "في المحتوى والتعليقات", "goToPrevious": "الانتقال إلى السابق", "goToNext": "الانتقال إلى التالي", "numberOfMatches": "{matches} نتائج", "nodeDetails": "تفاصيل", "enterComment": "الرجاء إدخال تعليق", "userCommentSave": "حفظ", "userCommentCancel": "إلغاء", "userCommentClear": "مسح" }, "bg": { "chatTreeRunning": "🥳🌳ChatTree🌳работи!🎉", "updateCurrentConversationTree": "🌈 Актуализация на текущото дърво на разговори 🌈", "adjustBackgroundColorAndOpacity": "🎨 Регулиране на цвета на фона и прозрачността 🎨", "toggleConversationTree": "🌳 Показване/скриване на дървото на разговори 🌳", "noDatabaseAndCreationFailed": "Няма база данни и създаването не бе успешно! Скриптът излиза!", "mismatchedLink": "Линкът не съответства, моля, опреснете страницата!", "startUpdatingConversationTree": "Започнете актуализация на дървото на разговори", "selectedItem": "Избрахте {item}", "successSavingChanges": "Промените са запазени успешно!", "codeCopiedToClipboard": "Кодът е копиран в клипборда!", "contentCopied": "Съдържанието е копирано!", "emptyCommentPrompt": "Коментарът е празен. Искате ли да зададете коментар като \\"празен\\"?", "confirmDeleteLinkData": "Линкът е проверен като {item}! Сигурни ли сте, че искате да изтриете информацията за този линк? Всички съдържания на разговори и коментари ще бъдат изтрити!", "confirmCurrentURL": "Линкът е проверен като {item}! Сигурни ли сте?", "commentSetToEmpty": "Коментарът е зададен като \\"празен\\"", "enterCommentFirst": "Моля, първо въведете коментар", "commentSaved": "Коментарът е запазен", "conversationDataDeleted": "Данните за разговора са изтрити успешно", "executeSearchWithQuery": "Изпълнение на търсене: {item}", "searchPlaceholder": "Въведете ключови думи за търсене...", "searchButton": "Търсене", "searchInContent": "В съдържанието на разговора", "searchInComments": "В коментарите", "searchInBoth": "В съдържание и коментари", "goToPrevious": "Към предишния", "goToNext": "Към следващия", "numberOfMatches": "{matches} съвпадения", "nodeDetails": "Подробности", "enterComment": "Моля, въведете коментар", "userCommentSave": "Запази", "userCommentCancel": "Отказ", "userCommentClear": "Изчисти" }, "cs": { "chatTreeRunning": "🥳🌳ChatTree🌳běží!🎉", "updateCurrentConversationTree": "🌈 Aktualizovat aktuální strom konverzace 🌈", "adjustBackgroundColorAndOpacity": "🎨 Upravit barvu pozadí a průhlednost 🎨", "toggleConversationTree": "🌳 Zobrazit/skrýt strom konverzace 🌳", "noDatabaseAndCreationFailed": "Není databáze a vytvoření se nezdařilo! Skript se ukončuje!", "mismatchedLink": "Odkaz nesouzní, obnovte stránku!", "startUpdatingConversationTree": "Začít aktualizovat strom konverzace", "selectedItem": "Vybrali jste {item}", "successSavingChanges": "Změny byly úspěšně uloženy!", "codeCopiedToClipboard": "Kód byl zkopírován do schránky!", "contentCopied": "Obsah byl zkopírován!", "emptyCommentPrompt": "Komentář je prázdný. Chcete nastavit komentář na \\"prázdný\\"?", "confirmDeleteLinkData": "Odkaz byl ověřen jako {item}! Opravdu chcete smazat informace tohoto odkazu? Veškerý obsah konverzace a komentáře budou smazány!", "confirmCurrentURL": "Odkaz byl ověřen jako {item}! Potvrzujete?", "commentSetToEmpty": "Komentář byl nastaven na \\"prázdný\\"", "enterCommentFirst": "Nejprve zadejte komentář", "commentSaved": "Komentář byl uložen", "conversationDataDeleted": "Data konverzace byla úspěšně smazána", "executeSearchWithQuery": "Spustit vyhledávání: {item}", "searchPlaceholder": "Zadejte klíčová slova pro vyhledávání...", "searchButton": "Hledat", "searchInContent": "Ve obsahu konverzace", "searchInComments": "V komentářích", "searchInBoth": "V obsahu i komentářích", "goToPrevious": "Jít na předchozí", "goToNext": "Jít na další", "numberOfMatches": "{matches} shod", "nodeDetails": "Detaily", "enterComment": "Zadejte komentář", "userCommentSave": "Uložit", "userCommentCancel": "Zrušit", "userCommentClear": "Vymazat" }, "da": { "chatTreeRunning": "🥳🌳ChatTree🌳 kører!🎉", "updateCurrentConversationTree": "🌈 Opdater nuværende samtaletræ 🌈", "adjustBackgroundColorAndOpacity": "🎨 Juster baggrundsfarve og gennemsigtighed 🎨", "toggleConversationTree": "🌳 Vis/skjul samtaletræ 🌳", "noDatabaseAndCreationFailed": "Ingen database, og oprettelsen mislykkedes! Scriptet afslutter!", "mismatchedLink": "Link matcher ikke, opdater siden!", "startUpdatingConversationTree": "Begynder at opdatere samtaletræ", "selectedItem": "Du valgte {item}", "successSavingChanges": "Ændringer gemt succesfuldt!", "codeCopiedToClipboard": "Kode kopieret til udklipsholder!", "contentCopied": "Indhold kopieret!", "emptyCommentPrompt": "Kommentaren er tom. Vil du sætte kommentaren til \\"tom\\"?", "confirmDeleteLinkData": "Linket er {item}! Er du sikker på, at du vil slette disse linkdata? Alle samtaler og kommentarer vil blive slettet!", "confirmCurrentURL": "Linket er {item}! Er du sikker?", "commentSetToEmpty": "Kommentar sat til \\"tom\\"", "enterCommentFirst": "Indtast kommentar først", "commentSaved": "Kommentar gemt", "conversationDataDeleted": "Samtaledata slettet succesfuldt", "executeSearchWithQuery": "Udfør søgning: {item}", "searchPlaceholder": "Indtast søgeord...", "searchButton": "Søg", "searchInContent": "I samtaleindholdet", "searchInComments": "I kommentarer", "searchInBoth": "Både i indhold og kommentarer", "goToPrevious": "Gå til den forrige", "goToNext": "Gå til den næste", "numberOfMatches": "{matches} match", "nodeDetails": "Detaljer", "enterComment": "Indtast kommentar", "userCommentSave": "Gem", "userCommentCancel": "Annuller", "userCommentClear": "Ryd" }, "de": { "chatTreeRunning": "🥳🌳ChatTree🌳 läuft!🎉", "updateCurrentConversationTree": "🌈 Aktualisiere aktuellen Konversationsbaum 🌈", "adjustBackgroundColorAndOpacity": "🎨 Hintergrundfarbe und Transparenz anpassen 🎨", "toggleConversationTree": "🌳 Konversationsbaum anzeigen/verbergen 🌳", "noDatabaseAndCreationFailed": "Keine Datenbank und Erstellung fehlgeschlagen! Skript beendet!", "mismatchedLink": "Link stimmt nicht überein, bitte aktualisieren Sie die Seite!", "startUpdatingConversationTree": "Beginne mit der Aktualisierung des Konversationsbaums", "selectedItem": "Sie haben {item} ausgewählt", "successSavingChanges": "Änderungen erfolgreich gespeichert!", "codeCopiedToClipboard": "Code wurde in die Zwischenablage kopiert!", "contentCopied": "Inhalt kopiert!", "emptyCommentPrompt": "Der Kommentar ist leer. Möchten Sie den Kommentar auf \\"leer\\" setzen?", "confirmDeleteLinkData": "Der erkannte Link ist {item}! Möchten Sie wirklich die Informationen zu diesem Link löschen? Alle Gesprächsinhalte und Kommentare werden gelöscht!", "confirmCurrentURL": "Der erkannte Link ist {item}! Sicher?", "commentSetToEmpty": "Kommentar auf \\"leer\\" gesetzt", "enterCommentFirst": "Bitte geben Sie zuerst einen Kommentar ein", "commentSaved": "Kommentar gespeichert", "conversationDataDeleted": "Konversationsdaten erfolgreich gelöscht", "executeSearchWithQuery": "Suche ausführen: {item}", "searchPlaceholder": "Suchbegriffe eingeben...", "searchButton": "Suchen", "searchInContent": "Im Gesprächsinhalt", "searchInComments": "In den Kommentaren", "searchInBoth": "In Inhalt und Kommentaren", "goToPrevious": "Zum vorherigen gehen", "goToNext": "Zum nächsten gehen", "numberOfMatches": "{matches} Übereinstimmungen", "nodeDetails": "Details", "enterComment": "Bitte Kommentar eingeben", "userCommentSave": "Speichern", "userCommentCancel": "Abbrechen", "userCommentClear": "Löschen" }, "el": { "chatTreeRunning": "🥳🌳ChatTree🌳 Είναι σε λειτουργία!🎉", "updateCurrentConversationTree": "🌈 Ενημέρωση του τρέχοντος δέντρου συνομιλίας 🌈", "adjustBackgroundColorAndOpacity": "🎨 Ρύθμιση του χρώματος φόντου και της διαφάνειας 🎨", "toggleConversationTree": "🌳 Εμφάνιση/Απόκρυψη δέντρου συνομιλίας 🌳", "noDatabaseAndCreationFailed": "Δεν υπάρχει βάση δεδομένων και η δημιουργία απέτυχε! Το σενάριο τερματίζεται!", "mismatchedLink": "Ο σύνδεσμος δεν ταιριάζει, παρακαλώ ανανεώστε τη σελίδα!", "startUpdatingConversationTree": "Ξεκινώντας την ενημέρωση του δέντρου συνομιλίας", "selectedItem": "Επιλέξατε {item}", "successSavingChanges": "Οι αλλαγές αποθηκεύτηκαν επιτυχώς!", "codeCopiedToClipboard": "Ο κώδικας αντιγράφηκε στο πρόχειρο!", "contentCopied": "Το περιεχόμενο αντιγράφηκε!", "emptyCommentPrompt": "Το σχόλιο είναι κενό. Θέλετε να ορίσετε το σχόλιο ως \\"κενό\\";", "confirmDeleteLinkData": "Ο σύνδεσμος που εντοπίστηκε είναι {item}! Είστε σίγουροι ότι θέλετε να διαγράψετε αυτά τα δεδομένα συνδέσμου; Όλο το περιεχόμενο της συζήτησης και τα σχόλια θα διαγραφούν!", "confirmCurrentURL": "Ο σύνδεσμος που εντοπίστηκε είναι {item}! Είστε σίγουροι;", "commentSetToEmpty": "Το σχόλιο ορίστηκε ως \\"κενό\\"", "enterCommentFirst": "Παρακαλώ εισάγετε πρώτα ένα σχόλιο", "commentSaved": "Το σχόλιο αποθηκεύτηκε", "conversationDataDeleted": "Τα δεδομένα συνομιλίας διαγράφηκαν επιτυχώς", "executeSearchWithQuery": "Εκτέλεση αναζήτησης: {item}", "searchPlaceholder": "Εισάγετε λέξεις κλειδιά αναζήτησης...", "searchButton": "Αναζήτηση", "searchInContent": "Στο περιεχόμενο της συνομιλίας", "searchInComments": "Στα σχόλια", "searchInBoth": "Τόσο στο περιεχόμενο όσο και στα σχόλια", "goToPrevious": "Πήγαινε στο προηγούμενο", "goToNext": "Πήγαινε στο επόμενο", "numberOfMatches": "{matches} αντιστοιχίες", "nodeDetails": "Λεπτομέρειες", "enterComment": "Πληκτρολογήστε σχόλιο", "userCommentSave": "Αποθήκευση", "userCommentCancel": "Ακύρωση", "userCommentClear": "Καθαρισμός" }, "en": { "chatTreeRunning": "🥳🌳ChatTree🌳 is Running!🎉", "updateCurrentConversationTree": "🌈 Update Current Conversation Tree 🌈", "adjustBackgroundColorAndOpacity": "🎨 Adjust Background Color and Opacity 🎨", "toggleConversationTree": "🌳 Show/Hide Conversation Tree 🌳", "noDatabaseAndCreationFailed": "No database, and creation failed! The script is terminating.", "mismatchedLink": "Link does not match, please refresh the page!", "startUpdatingConversationTree": "Starting to update the conversation tree", "selectedItem": "You selected {item}", "successSavingChanges": "Changes Saved Successfully!", "codeCopiedToClipboard": "Code Copied to Clipboard!", "contentCopied": "Content Copied!", "emptyCommentPrompt": "The comment is empty. Do you want to set the comment to \\"empty\\"?", "confirmDeleteLinkData": "Detected link is {item}! Are you sure you want to delete this link's information? All conversation content and comments will be deleted!", "confirmCurrentURL": "Detected link is {item}! Are you sure?", "commentSetToEmpty": "Comment set to \\"empty\\"", "enterCommentFirst": "Please enter a comment first", "commentSaved": "Comment Saved", "conversationDataDeleted": "Conversation Data Successfully Deleted", "executeSearchWithQuery": "Executing Search: {item}", "searchPlaceholder": "Enter search keywords...", "searchButton": "Search", "searchInContent": "Conversation Content", "searchInComments": "User Comments", "searchInBoth": "Content & Comments", "goToPrevious": "Go to Previous", "goToNext": "Go to Next", "numberOfMatches": "{matches} matches found", "nodeDetails": "Details", "enterComment": "Please Enter Comment", "userCommentSave": "Save", "userCommentCancel": "Cancel", "userCommentClear": "Clear" }, "eo": { "chatTreeRunning": "🥳🌳ChatTree🌳 funkcias!🎉", "updateCurrentConversationTree": "🌈 Ĝisdatigi la aktivan konversacian arbon 🌈", "adjustBackgroundColorAndOpacity": "🎨 Agordi fondon koloron kaj opakecon 🎨", "toggleConversationTree": "🌳 Montri/Kaŝi konversacian arbon 🌳", "noDatabaseAndCreationFailed": "Neniu datumbazo, kaj ne sukcesis krei! Skripto eliras!", "mismatchedLink": "Ligilo ne kongruas, bonvolu refreŝigi la paĝon!", "startUpdatingConversationTree": "Komenci ĝisdatigi la konversacian arbon", "selectedItem": "Vi selektis {item}", "successSavingChanges": "Ŝanĝoj sukcese konservitaj!", "codeCopiedToClipboard": "Kodo estis kopii al tondejo!", "contentCopied": "Enhavo estis kopii!", "emptyCommentPrompt": "Komento estas malplena. Ĉu vi volas agordi komenton al \\"malplena\\"?", "confirmDeleteLinkData": "Detektis ligilon {item}! Ĉu vi certas, ke vi volas forigi ĉi tiun ligilon informon? Ĉiuj konversaciaj enhavoj kaj komentoj estos forigitaj!", "confirmCurrentURL": "Detektis ligilon {item}! Ĉu vi certas?", "commentSetToEmpty": "Komento estis agordita al \\"malplena\\"", "enterCommentFirst": "Bonvolu unue enigi komenton", "commentSaved": "Komento konservita", "conversationDataDeleted": "Konversaciaj datenoj sukcese forigitaj", "executeSearchWithQuery": "Efektivi serĉon: {item}", "searchPlaceholder": "Enmetu serĉajn ŝlosilvortojn...", "searchButton": "Serĉi", "searchInContent": "Konversacia enhavo", "searchInComments": "Komentoj de uzantoj", "searchInBoth": "Enhavo & Komentoj", "goToPrevious": "Iru al antaŭa", "goToNext": "Iru al sekvanta", "numberOfMatches": "{matches} kongruajn trovis", "nodeDetails": "Detaloj", "enterComment": "Bonvolu Enmeti Komenton", "userCommentSave": "Konservi", "userCommentCancel": "Nuligi", "userCommentClear": "Forigi" }, "es": { "chatTreeRunning": "🥳🌳¡ChatTree🌳 en funcionamiento!🎉", "updateCurrentConversationTree": "🌈 Actualizar el árbol de conversación actual 🌈", "adjustBackgroundColorAndOpacity": "🎨 Ajustar color de fondo y opacidad 🎨", "toggleConversationTree": "🌳 Mostrar/Ocultar árbol de conversación 🌳", "noDatabaseAndCreationFailed": "¡No hay base de datos y no se pudo crear! ¡Saliendo del script!", "mismatchedLink": "¡El enlace no coincide, por favor actualiza la página!", "startUpdatingConversationTree": "Comenzar a actualizar el árbol de conversación", "selectedItem": "Seleccionaste {item}", "successSavingChanges": "¡Cambios guardados con éxito!", "codeCopiedToClipboard": "¡Código copiado al portapapeles!", "contentCopied": "¡Contenido copiado!", "emptyCommentPrompt": "El comentario está vacío. ¿Quieres establecer el comentario como \\"vacío\\"?", "confirmDeleteLinkData": "¡Se detectó el enlace {item}! ¿Estás seguro de que quieres eliminar la información de este enlace? ¡Toda la conversación y los comentarios se eliminarán!", "confirmCurrentURL": "¡Se detectó el enlace {item}! ¿Estás seguro?", "commentSetToEmpty": "Comentario establecido como \\"vacío\\"", "enterCommentFirst": "Por favor, ingresa un comentario primero", "commentSaved": "Comentario guardado", "conversationDataDeleted": "Datos de la conversación eliminados con éxito", "executeSearchWithQuery": "Ejecutar búsqueda: {item}", "searchPlaceholder": "Ingrese palabras clave para buscar...", "searchButton": "Buscar", "searchInContent": "Contenido de la conversación", "searchInComments": "Comentarios de usuarios", "searchInBoth": "Contenido y comentarios", "goToPrevious": "Ir al anterior", "goToNext": "Ir al siguiente", "numberOfMatches": "{matches} coincidencias encontradas", "nodeDetails": "Detalles", "enterComment": "Por Favor Introduce un Comentario", "userCommentSave": "Guardar", "userCommentCancel": "Cancelar", "userCommentClear": "Borrar" }, "fi": { "chatTreeRunning": "🥳🌳ChatTree🌳 on käynnissä!🎉", "updateCurrentConversationTree": "🌈 Päivitä nykyinen keskustelupuu 🌈", "adjustBackgroundColorAndOpacity": "🎨 Säädä taustavärin ja läpinäkyvyyden 🎨", "toggleConversationTree": "🌳 Näytä/Piilota keskustelupuu 🌳", "noDatabaseAndCreationFailed": "Tietokantaa ei ole, eikä luonti onnistunut! Skripti päättyy!", "mismatchedLink": "Linkki ei täsmää, päivitä sivu!", "startUpdatingConversationTree": "Aloita keskustelupuun päivittäminen", "selectedItem": "Valitsit kohteen {item}", "successSavingChanges": "Muutosten tallennus onnistui!", "codeCopiedToClipboard": "Koodi kopioitu leikepöydälle!", "contentCopied": "Sisältö kopioitu!", "emptyCommentPrompt": "Kommentti on tyhjä. Haluatko asettaa kommentin \\"tyhjäksi\\"?", "confirmDeleteLinkData": "Linkki {item} havaittu! Haluatko varmasti poistaa tämän linkin tiedot? Kaikki keskustelut ja kommentit poistetaan!", "confirmCurrentURL": "Linkki {item} havaittu! Oletko varma?", "commentSetToEmpty": "Kommentti asetettu \\"tyhjäksi\\"", "enterCommentFirst": "Syötä kommentti ensin", "commentSaved": "Kommentti tallennettu", "conversationDataDeleted": "Keskustelutiedot poistettu onnistuneesti", "executeSearchWithQuery": "Suorita haku: {item}", "searchPlaceholder": "Anna hakusanat...", "searchButton": "Hae", "searchInContent": "Keskustelun sisältö", "searchInComments": "Käyttäjien kommentit", "searchInBoth": "Sisältö ja kommentit", "goToPrevious": "Mene edelliseen", "goToNext": "Mene seuraavaan", "numberOfMatches": "{matches} osumaa löydetty", "nodeDetails": "Tiedot", "enterComment": "Ole Hyvä ja Kirjoita Kommentti", "userCommentSave": "Tallenna", "userCommentCancel": "Peruuta", "userCommentClear": "Tyhjennä" }, "fr": { "chatTreeRunning": "🥳🌳ChatTree🌳 est en cours d'exécution !🎉", "updateCurrentConversationTree": "🌈 Mettre à jour l'arbre de conversation actuel 🌈", "adjustBackgroundColorAndOpacity": "🎨 Ajuster la couleur de fond et l'opacité 🎨", "toggleConversationTree": "🌳 Afficher/Masquer l'arbre de conversation 🌳", "noDatabaseAndCreationFailed": "Pas de base de données et la création a échoué ! Sortie du script !", "mismatchedLink": "Le lien ne correspond pas, veuillez rafraîchir la page !", "startUpdatingConversationTree": "Commencer à mettre à jour l'arbre de conversation", "selectedItem": "Vous avez sélectionné {item}", "successSavingChanges": "Modifications enregistrées avec succès !", "codeCopiedToClipboard": "Le code a été copié dans le presse-papiers !", "contentCopied": "Contenu copié !", "emptyCommentPrompt": "Le commentaire est vide. Voulez-vous définir le commentaire comme \\"vide\\" ?", "confirmDeleteLinkData": "Le lien {item} a été détecté ! Êtes-vous sûr de vouloir supprimer les informations de ce lien ? Toutes les conversations et les commentaires seront supprimés !", "confirmCurrentURL": "Le lien {item} a été détecté ! Êtes-vous sûr ?", "commentSetToEmpty": "Commentaire défini comme \\"vide\\"", "enterCommentFirst": "Veuillez d'abord entrer un commentaire", "commentSaved": "Commentaire enregistré", "conversationDataDeleted": "Données de conversation supprimées avec succès", "executeSearchWithQuery": "Effectuer une recherche : {item}", "searchPlaceholder": "Entrez des mots-clés pour rechercher...", "searchButton": "Rechercher", "searchInContent": "Contenu de la conversation", "searchInComments": "Commentaires des utilisateurs", "searchInBoth": "Contenu et commentaires", "goToPrevious": "Aller au précédent", "goToNext": "Aller au suivant", "numberOfMatches": "{matches} correspondances trouvées", "nodeDetails": "Détails", "enterComment": "Veuillez Entrer un Commentaire", "userCommentSave": "Enregistrer", "userCommentCancel": "Annuler", "userCommentClear": "Effacer" }, "fr-CA": { "chatTreeRunning": "🥳🌳ChatTree🌳 est en marche !🎉", "updateCurrentConversationTree": "🌈 Mettre à jour l'arbre de conversation actuel 🌈", "adjustBackgroundColorAndOpacity": "🎨 Ajustez la couleur de fond et l'opacité 🎨", "toggleConversationTree": "🌳 Afficher/Masquer l'arbre de conversation 🌳", "noDatabaseAndCreationFailed": "Pas de base de données et la création a échoué ! Le script se termine !", "mismatchedLink": "Le lien ne correspond pas, veuillez rafraîchir la page !", "startUpdatingConversationTree": "Commencer la mise à jour de l'arbre de conversation", "selectedItem": "Vous avez sélectionné {item}", "successSavingChanges": "Modifications enregistrées avec succès !", "codeCopiedToClipboard": "Le code a été copié dans le presse-papiers !", "contentCopied": "Contenu copié !", "emptyCommentPrompt": "Le commentaire est vide. Souhaitez-vous définir le commentaire comme \\"vide\\" ?", "confirmDeleteLinkData": "Le lien {item} a été détecté ! Êtes-vous sûr de vouloir supprimer les données de ce lien ? Toutes les conversations et les commentaires seront supprimés !", "confirmCurrentURL": "Le lien {item} a été détecté ! Êtes-vous sûr ?", "commentSetToEmpty": "Commentaire défini comme \\"vide\\"", "enterCommentFirst": "Veuillez d'abord entrer un commentaire", "commentSaved": "Commentaire sauvegardé", "conversationDataDeleted": "Données de conversation supprimées avec succès", "executeSearchWithQuery": "Exécuter la recherche : {item}", "searchPlaceholder": "Entrez des mots-clés pour chercher...", "searchButton": "Rechercher", "searchInContent": "Contenu de la conversation", "searchInComments": "Commentaires des utilisateurs", "searchInBoth": "Contenu et commentaires", "goToPrevious": "Aller au précédent", "goToNext": "Aller au suivant", "numberOfMatches": "{matches} correspondances trouvées", "nodeDetails": "Détails", "enterComment": "Veuillez Entrer un Commentaire", "userCommentSave": "Enregistrer", "userCommentCancel": "Annuler", "userCommentClear": "Effacer" }, "he": { "chatTreeRunning": "🥳🌳ChatTree🌳 פועל!🎉", "updateCurrentConversationTree": "🌈 עדכן את עץ השיחה הנוכחי 🌈", "adjustBackgroundColorAndOpacity": "🎨 כוונן את צבע הרקע והשקיפות 🎨", "toggleConversationTree": "🌳 הצג/הסתר עץ שיחה 🌳", "noDatabaseAndCreationFailed": "אין מסד נתונים ויצירתו נכשלה! סקריפט יוצא!", "mismatchedLink": "הקישור אינו תואם, אנא רענן את הדף!", "startUpdatingConversationTree": "התחל לעדכן את עץ השיחה", "selectedItem": "בחרת {item}", "successSavingChanges": "השינויים נשמרו בהצלחה!", "codeCopiedToClipboard": "הקוד הועתק ללוח!", "contentCopied": "התוכן הועתק!", "emptyCommentPrompt": "ההערה ריקה. האם תרצה להגדיר את ההערה כ\\"ריקה\\"?", "confirmDeleteLinkData": "הקישור {item} זוהה! האם אתה בטוח שאתה רוצה למחוק את נתוני הקישור הזה? כל השיחות וההערות יימחקו!", "confirmCurrentURL": "הקישור {item} זוהה! האם אתה בטוח?", "commentSetToEmpty": "ההערה הוגדרה כ\\"ריקה\\"", "enterCommentFirst": "אנא הזן הערה קודם", "commentSaved": "ההערה נשמרה", "conversationDataDeleted": "נתוני השיחה נמחקו בהצלחה", "executeSearchWithQuery": "בצע חיפוש: {item}", "searchPlaceholder": "הזן מילות חיפוש...", "searchButton": "חפש", "searchInContent": "תוכן השיחה", "searchInComments": "הערות משתמש", "searchInBoth": "תוכן והערות", "goToPrevious": "עבור לקודם", "goToNext": "עבור להבא", "numberOfMatches": "{matches} תוצאות", "nodeDetails": "פרטים", "enterComment": "אנא הקלד תגובה", "userCommentSave": "שמור", "userCommentCancel": "בטל", "userCommentClear": "נקה" }, "hu": { "chatTreeRunning": "🥳🌳ChatTree🌳 fut!🎉", "updateCurrentConversationTree": "🌈 Frissítsd az aktuális beszélgetésfát 🌈", "adjustBackgroundColorAndOpacity": "🎨 Állítsd be a háttérszín és az átlátszóság értékeit 🎨", "toggleConversationTree": "🌳 Beszélgetésfa megjelenítése/elrejtése 🌳", "noDatabaseAndCreationFailed": "Nincs adatbázis és a létrehozás sikertelen! A szkript kilép!", "mismatchedLink": "A link nem egyezik, kérjük, frissítse az oldalt!", "startUpdatingConversationTree": "Beszélgetésfa frissítésének kezdése", "selectedItem": "Kiválasztott elem: {item}", "successSavingChanges": "A változások mentése sikerült!", "codeCopiedToClipboard": "A kód vágólapra másolva!", "contentCopied": "A tartalom másolva!", "emptyCommentPrompt": "A megjegyzés üres. Beállítja \\"üres\\"-ként?", "confirmDeleteLinkData": "A {item} link észlelve! Biztosan törli e link adatát? Minden beszélgetés és megjegyzés törlődik!", "confirmCurrentURL": "A {item} link észlelve! Biztos benne?", "commentSetToEmpty": "A megjegyzés \\"üres\\"-re van állítva", "enterCommentFirst": "Kérjük, először írja be a megjegyzést", "commentSaved": "Megjegyzés mentve", "conversationDataDeleted": "A beszélgetés adatai sikeresen törölve", "executeSearchWithQuery": "Keresés indítása: {item}", "searchPlaceholder": "Írja be a keresendő kifejezéseket...", "searchButton": "Keresés", "searchInContent": "Beszélgetés tartalma", "searchInComments": "Felhasználói megjegyzések", "searchInBoth": "Tartalom és megjegyzések", "goToPrevious": "Ugrás az előzőre", "goToNext": "Ugrás a következőre", "numberOfMatches": "{matches} találat", "nodeDetails": "Részletek", "enterComment": "Kérjük, írja be a megjegyzést", "userCommentSave": "Mentés", "userCommentCancel": "Mégse", "userCommentClear": "Törlés" }, "id": { "chatTreeRunning": "🥳🌳ChatTree🌳 Sedang Berjalan!🎉", "updateCurrentConversationTree": "🌈 Perbarui Pohon Percakapan Saat Ini 🌈", "adjustBackgroundColorAndOpacity": "🎨 Sesuaikan Warna Latar Belakang dan Kecerahan 🎨", "toggleConversationTree": "🌳 Tampilkan/Sembunyikan Pohon Percakapan 🌳", "noDatabaseAndCreationFailed": "Tidak ada database, dan pembuatan gagal! Script keluar!", "mismatchedLink": "Tautan tidak cocok, silakan segarkan halaman!", "startUpdatingConversationTree": "Mulai memperbarui Pohon Percakapan", "selectedItem": "Anda memilih {item}", "successSavingChanges": "Berhasil Menyimpan Perubahan!", "codeCopiedToClipboard": "Kode disalin ke papan klip!", "contentCopied": "Konten disalin!", "emptyCommentPrompt": "Komentar kosong. Apakah Anda ingin mengatur komentar ke \\"kosong\\"?", "confirmDeleteLinkData": "Tautan {item} terdeteksi! Apakah Anda yakin ingin menghapus data tautan ini? Semua konten percakapan dan komentar akan dihapus!", "confirmCurrentURL": "Tautan {item} terdeteksi! Apakah Anda yakin?", "commentSetToEmpty": "Komentar diatur ke \\"kosong\\"", "enterCommentFirst": "Silakan masukkan komentar terlebih dahulu", "commentSaved": "Komentar disimpan", "conversationDataDeleted": "Data Percakapan Berhasil Dihapus", "executeSearchWithQuery": "Melakukan pencarian: {item}", "searchPlaceholder": "Masukkan kata kunci pencarian...", "searchButton": "Cari", "searchInContent": "Konten Percakapan", "searchInComments": "Komentar Pengguna", "searchInBoth": "Konten dan Komentar", "goToPrevious": "Pergi ke Sebelumnya", "goToNext": "Pergi ke Berikutnya", "numberOfMatches": "{matches} hasil pencarian", "nodeDetails": "Detail", "enterComment": "Silakan masukkan komentar", "userCommentSave": "Simpan", "userCommentCancel": "Batal", "userCommentClear": "Hapus" }, "it": { "chatTreeRunning": "🥳🌳ChatTree🌳 in esecuzione!🎉", "updateCurrentConversationTree": "🌈 Aggiorna l'albero di conversazione corrente 🌈", "adjustBackgroundColorAndOpacity": "🎨 Ajusta il colore di sfondo e l'opacità 🎨", "toggleConversationTree": "🌳 Mostra/Nascondi l'albero di conversazione 🌳", "noDatabaseAndCreationFailed": "Nessun database e la creazione non è riuscita! Script interrotto!", "mismatchedLink": "Il link non corrisponde, si prega di aggiornare la pagina!", "startUpdatingConversationTree": "Inizia l'aggiornamento dell'albero di conversazione", "selectedItem": "Hai selezionato {item}", "successSavingChanges": "Modifiche salvate con successo!", "codeCopiedToClipboard": "Codice copiato negli appunti!", "contentCopied": "Contenuto copiato!", "emptyCommentPrompt": "Il commento è vuoto. Vuoi impostare il commento su 'vuoto'?", "confirmDeleteLinkData": "Link rilevato {item}! Sei sicuro di voler eliminare le informazioni di questo link? Tutti i contenuti della conversazione e i commenti verranno eliminati!", "confirmCurrentURL": "Link rilevato {item}! Confermi?", "commentSetToEmpty": "Il commento è stato impostato su 'vuoto'", "enterCommentFirst": "Per favore, inserisci prima un commento", "commentSaved": "Commento salvato", "conversationDataDeleted": "Dati della conversazione eliminati con successo", "executeSearchWithQuery": "Esegui ricerca: {item}", "searchPlaceholder": "Inserisci parole chiave per la ricerca...", "searchButton": "Cerca", "searchInContent": "Contenuto della conversazione", "searchInComments": "Commenti degli utenti", "searchInBoth": "Contenuti e commenti", "goToPrevious": "Vai al precedente", "goToNext": "Vai al successivo", "numberOfMatches": "{matches} corrispondenze trovate", "nodeDetails": "Dettagli", "enterComment": "Per favore, inserisci un commento", "userCommentSave": "Salva", "userCommentCancel": "Annulla", "userCommentClear": "Cancella" }, "ja": { "chatTreeRunning": "🥳🌳ChatTree🌳実行中!🎉", "updateCurrentConversationTree": "🌈 現在の会話ツリーを更新 🌈", "adjustBackgroundColorAndOpacity": "🎨 背景色と透明度を調整 🎨", "toggleConversationTree": "🌳 会話ツリーを表示/非表示 🌳", "noDatabaseAndCreationFailed": "データベースがなく、作成に失敗しました!スクリプトを終了します!", "mismatchedLink": "リンクが一致しません、ページを更新してください!", "startUpdatingConversationTree": "会話ツリーの更新を開始", "selectedItem": "{item}を選択しました", "successSavingChanges": "変更の保存に成功しました!", "codeCopiedToClipboard": "コードがクリップボードにコピーされました!", "contentCopied": "内容がコピーされました!", "emptyCommentPrompt": "コメントが空です。コメントを'空'に設定しますか?", "confirmDeleteLinkData": "{item}のリンクが検出されました! このリンクの情報を削除してもよろしいですか? すべての会話内容とコメントが削除されます!", "confirmCurrentURL": "{item}のリンクが検出されました!よろしいですか?", "commentSetToEmpty": "コメントが'空'に設定されました", "enterCommentFirst": "先にコメントを入力してください", "commentSaved": "コメントが保存されました", "conversationDataDeleted": "会話データが正常に削除されました", "executeSearchWithQuery": "検索を実行:{item}", "searchPlaceholder": "検索キーワードを入力...", "searchButton": "検索", "searchInContent": "会話の内容", "searchInComments": "ユーザーコメント", "searchInBoth": "内容とコメント", "goToPrevious": "前へ", "goToNext": "次へ", "numberOfMatches": "一致する項目{matches}件", "nodeDetails": "詳細", "enterComment": "コメントを入力してください", "userCommentSave": "保存", "userCommentCancel": "キャンセル", "userCommentClear": "クリア" }, "ka": { "chatTreeRunning": "🥳🌳ChatTree🌳 გაშვებულია!🎉", "updateCurrentConversationTree": "🌈 განაახლეთ ამჟამინდელი სასაუბრო ხე 🌈", "adjustBackgroundColorAndOpacity": "🎨 გაასწორეთ ფონის ფერი და გამჭვირვალობა 🎨", "toggleConversationTree": "🌳 ჩვენება/დამალვა სასაუბრო ხე 🌳", "noDatabaseAndCreationFailed": "არ არის მონაცემთა ბაზა და შექმნა ვერ ხერხდება! სკრიპტი გამოირიყება!", "mismatchedLink": "ბმული არ ემთხვევა, გთხოვთ, განაახლოთ გვერდი!", "startUpdatingConversationTree": "სასაუბრო ხის განახლების დაწყება", "selectedItem": "თქვენ აირჩიეთ {item}", "successSavingChanges": "ცვლილებები წარმატებით შენახულია!", "codeCopiedToClipboard": "კოდი კოპირებულია ბუფერში!", "contentCopied": "კონტენტი კოპირებულია!", "emptyCommentPrompt": "კომენტარი ცარიელია. გსურთ კომენტარი 'ცარიელი' განსაზღვროთ?", "confirmDeleteLinkData": "{item} ბმული აღმოჩენილია! დარწმუნებული ხართ, რომ გსურთ ამ ბმულის ინფორმაციის წაშლა? ყველა სასაუბრო კონტენტი და კომენტარი წაიშლება!", "confirmCurrentURL": "{item} ბმული აღმოჩენილია! დარწმუნებული ხართ?", "commentSetToEmpty": "კომენტარი 'ცარიელია' განსაზღვრულია", "enterCommentFirst": "გთხოვთ, ჯერ შეიყვანეთ კომენტარი", "commentSaved": "კომენტარი შენახულია", "conversationDataDeleted": "სასაუბრო მონაცემები წარმატებით წაიშალა", "executeSearchWithQuery": "ძიება შესრულება: {item}", "searchPlaceholder": "შეიყვანეთ ძიების სიტყვები...", "searchButton": "ძებნა", "searchInContent": "კონვერსიის კონტენტი", "searchInComments": "მომხმარებლის კომენტარები", "searchInBoth": "კონტენტი და კომენტარები", "goToPrevious": "წინაში გადასვლა", "goToNext": "შემდეგში გადასვლა", "numberOfMatches": "{matches} შესატყვისი", "nodeDetails": "დეტალები", "enterComment": "გთხოვთ შეიყვანოთ კომენტარი", "userCommentSave": "შენახვა", "userCommentCancel": "გაუქმება", "userCommentClear": "გასუფთავება" }, "ko": { "chatTreeRunning": "🥳🌳ChatTree🌳 실행 중!🎉", "updateCurrentConversationTree": "🌈 현재 대화 트리 업데이트 🌈", "adjustBackgroundColorAndOpacity": "🎨 배경색과 투명도 조정 🎨", "toggleConversationTree": "🌳 대화 트리 표시/숨기기 🌳", "noDatabaseAndCreationFailed": "데이터베이스가 없으며 생성에 실패했습니다! 스크립트 종료!", "mismatchedLink": "링크가 일치하지 않습니다. 페이지를 새로고침하세요!", "startUpdatingConversationTree": "대화 트리 업데이트 시작", "selectedItem": "{item}를 선택했습니다", "successSavingChanges": "변경 사항이 성공적으로 저장되었습니다!", "codeCopiedToClipboard": "코드가 클립보드에 복사되었습니다!", "contentCopied": "내용이 복사되었습니다!", "emptyCommentPrompt": "댓글이 비어 있습니다. 댓글을 '비움'으로 설정하시겠습니까?", "confirmDeleteLinkData": "{item} 링크를 감지했습니다! 이 링크의 정보를 삭제하시겠습니까? 모든 대화 내용과 댓글이 삭제됩니다!", "confirmCurrentURL": "{item} 링크를 감지했습니다! 확인하시겠습니까?", "commentSetToEmpty": "댓글이 '비움'으로 설정되었습니다", "enterCommentFirst": "먼저 댓글을 입력해주세요", "commentSaved": "댓글이 저장되었습니다", "conversationDataDeleted": "대화 데이터가 성공적으로 삭제되었습니다", "executeSearchWithQuery": "검색 실행: {item}", "searchPlaceholder": "검색어를 입력하세요...", "searchButton": "검색", "searchInContent": "대화 내용", "searchInComments": "사용자 코멘트", "searchInBoth": "내용과 코멘트", "goToPrevious": "이전으로", "goToNext": "다음으로", "numberOfMatches": "{matches}개의 일치 항목", "nodeDetails": "세부 정보", "enterComment": "댓글을 입력하세요", "userCommentSave": "저장", "userCommentCancel": "취소", "userCommentClear": "지우기" }, "nb": { "chatTreeRunning": "🥳🌳ChatTree🌳 er i gang! 🎉", "updateCurrentConversationTree": "🌈 Oppdater gjeldende samtale-tre 🌈", "adjustBackgroundColorAndOpacity": "🎨 Juster bakgrunnsfarge og opasitet 🎨", "toggleConversationTree": "🌳 Vis/Skjul samtale-tre 🌳", "noDatabaseAndCreationFailed": "Ingen database, og opprettelsen mislyktes! Skriptet avslutter!", "mismatchedLink": "Lenken stemmer ikke, vennligst oppfrisk siden!", "startUpdatingConversationTree": "Begynner å oppdatere samtale-treet", "selectedItem": "Du valgte {item}", "successSavingChanges": "Endringene ble lagret!", "codeCopiedToClipboard": "Koden er kopiert til utklippstavlen!", "contentCopied": "Innholdet er kopiert!", "emptyCommentPrompt": "Kommentaren er tom. Vil du sette kommentaren til \\"tom\\"?", "confirmDeleteLinkData": "Linken er {item}! Er du sikker på at du vil slette denne linkens informasjon? All samtale og kommentarinnhold vil bli slettet!", "confirmCurrentURL": "Linken er {item}! Er du sikker?", "commentSetToEmpty": "Kommentaren er satt til \\"tom\\"", "enterCommentFirst": "Vennligst skriv en kommentar først", "commentSaved": "Kommentaren er lagret", "conversationDataDeleted": "Samtaledata er slettet", "executeSearchWithQuery": "Utfør søk: {item}", "searchPlaceholder": "Skriv inn søkeord...", "searchButton": "Søk", "searchInContent": "Samtaleinnhold", "searchInComments": "Brukerkommentarer", "searchInBoth": "Innhold og kommentarer", "goToPrevious": "Gå til forrige", "goToNext": "Gå til neste", "numberOfMatches": "{matches} treff", "nodeDetails": "Detaljer", "enterComment": "Vennligst skriv en kommentar", "userCommentSave": "Lagre", "userCommentCancel": "Avbryt", "userCommentClear": "Tøm" }, "nl": { "chatTreeRunning": "🥳🌳ChatTree🌳 is actief! 🎉", "updateCurrentConversationTree": "🌈 Huidige gespreksboom bijwerken 🌈", "adjustBackgroundColorAndOpacity": "🎨 Achtergrondkleur en opaciteit aanpassen 🎨", "toggleConversationTree": "🌳 Gespreksboom weergeven/verbergen 🌳", "noDatabaseAndCreationFailed": "Geen database en het aanmaken is mislukt! Script wordt afgesloten!", "mismatchedLink": "Link komt niet overeen, ververs de pagina!", "startUpdatingConversationTree": "Begint met het bijwerken van de gespreksboom", "selectedItem": "Je hebt {item} geselecteerd", "successSavingChanges": "Wijzigingen succesvol opgeslagen!", "codeCopiedToClipboard": "Code gekopieerd naar klembord!", "contentCopied": "Inhoud gekopieerd!", "emptyCommentPrompt": "De opmerking is leeg. Wil je de opmerking instellen op \\"leeg\\"?", "confirmDeleteLinkData": "Gedetecteerde link is {item}! Weet je zeker dat je de informatie van deze link wilt verwijderen? Alle gespreks- en opmerkingsinhoud zal worden verwijderd!", "confirmCurrentURL": "Gedetecteerde link is {item}! Zeker weten?", "commentSetToEmpty": "Opmerking is ingesteld op \\"leeg\\"", "enterCommentFirst": "Voer eerst een opmerking in", "commentSaved": "Opmerking opgeslagen", "conversationDataDeleted": "Gespreksgegevens succesvol verwijderd", "executeSearchWithQuery": "Zoekopdracht uitvoeren: {item}", "searchPlaceholder": "Voer zoekwoorden in...", "searchButton": "Zoeken", "searchInContent": "In gespreksinhoud", "searchInComments": "In gebruikersopmerkingen", "searchInBoth": "In inhoud en opmerkingen", "goToPrevious": "Ga naar vorige", "goToNext": "Ga naar volgende", "numberOfMatches": "{matches} overeenkomsten", "nodeDetails": "Details", "enterComment": "Voer alstublieft een opmerking in", "userCommentSave": "Opslaan", "userCommentCancel": "Annuleren", "userCommentClear": "Wissen" }, "pl": { "chatTreeRunning": "🥳🌳ChatTree🌳 jest uruchomiony! 🎉", "updateCurrentConversationTree": "🌈 Aktualizuj aktualne drzewo rozmów 🌈", "adjustBackgroundColorAndOpacity": "🎨 Dostosuj kolor tła i przezroczystość 🎨", "toggleConversationTree": "🌳 Pokaż/ukryj drzewo rozmów 🌳", "noDatabaseAndCreationFailed": "Brak bazy danych, a jej utworzenie nie powiodło się! Skrypt zakończy działanie!", "mismatchedLink": "Link nie pasuje, odśwież stronę!", "startUpdatingConversationTree": "Rozpoczyna aktualizację drzewa rozmów", "selectedItem": "Wybrałeś {item}", "successSavingChanges": "Zmiany zostały zapisane!", "codeCopiedToClipboard": "Kod skopiowany do schowka!", "contentCopied": "Treść skopiowana!", "emptyCommentPrompt": "Komentarz jest pusty. Czy chcesz ustawić komentarz na \\"pusty\\"?", "confirmDeleteLinkData": "Wykryto link {item}! Czy na pewno chcesz usunąć informacje z tego linku? Wszystkie treści rozmów i komentarze zostaną usunięte!", "confirmCurrentURL": "Wykryto link {item}! Czy jesteś pewien?", "commentSetToEmpty": "Komentarz został ustawiony na \\"pusty\\"", "enterCommentFirst": "Najpierw wprowadź komentarz", "commentSaved": "Komentarz został zapisany", "conversationDataDeleted": "Dane rozmowy zostały pomyślnie usunięte", "executeSearchWithQuery": "Wykonaj wyszukiwanie: {item}", "searchPlaceholder": "Wprowadź słowa kluczowe...", "searchButton": "Szukaj", "searchInContent": "W treści rozmowy", "searchInComments": "W komentarzach użytkowników", "searchInBoth": "W treści i komentarzach", "goToPrevious": "Przejdź do poprzedniego", "goToNext": "Przejdź do następnego", "numberOfMatches": "{matches} dopasowań", "nodeDetails": "Szczegóły", "enterComment": "Proszę wprowadzić komentarz", "userCommentSave": "Zapisz", "userCommentCancel": "Anuluj", "userCommentClear": "Wyczyść" }, "pt-PT": { "chatTreeRunning": "🥳🌳ChatTree🌳 em execução! 🎉", "updateCurrentConversationTree": "🌈 Atualizar a árvore de conversação atual 🌈", "adjustBackgroundColorAndOpacity": "🎨 Ajustar a cor de fundo e a opacidade 🎨", "toggleConversationTree": "🌳 Mostrar/ocultar árvore de conversação 🌳", "noDatabaseAndCreationFailed": "Sem base de dados e a criação falhou! Script a encerrar!", "mismatchedLink": "Link não corresponde, por favor atualize a página!", "startUpdatingConversationTree": "A iniciar a atualização da árvore de conversação", "selectedItem": "Selecionou {item}", "successSavingChanges": "Alterações guardadas com sucesso!", "codeCopiedToClipboard": "Código copiado para a área de transferência!", "contentCopied": "Conteúdo copiado!", "emptyCommentPrompt": "O comentário está vazio. Deseja definir o comentário como \\"vazio\\"?", "confirmDeleteLinkData": "O link detetado é {item}! Tem a certeza que quer eliminar as informações deste link? Todo o conteúdo da conversa e comentários serão eliminados!", "confirmCurrentURL": "O link detetado é {item}! Confirma?", "commentSetToEmpty": "O comentário foi definido como \\"vazio\\"", "enterCommentFirst": "Por favor, insira um comentário primeiro", "commentSaved": "Comentário guardado", "conversationDataDeleted": "Dados de conversação eliminados com sucesso", "executeSearchWithQuery": "Executar pesquisa: {item}", "searchPlaceholder": "Insira palavras-chave...", "searchButton": "Pesquisar", "searchInContent": "No conteúdo da conversa", "searchInComments": "Nos comentários do usuário", "searchInBoth": "Em conteúdo e comentários", "goToPrevious": "Ir para o anterior", "goToNext": "Ir para o próximo", "numberOfMatches": "{matches} correspondências", "nodeDetails": "Detalhes", "enterComment": "Insira um comentário", "userCommentSave": "Guardar", "userCommentCancel": "Cancelar", "userCommentClear": "Limpar" }, "pt-BR": { "chatTreeRunning": "🥳🌳ChatTree🌳 em execução! 🎉", "updateCurrentConversationTree": "🌈 Atualizar a árvore de conversa atual 🌈", "adjustBackgroundColorAndOpacity": "🎨 Ajustar a cor de fundo e a opacidade 🎨", "toggleConversationTree": "🌳 Mostrar/esconder árvore de conversa 🌳", "noDatabaseAndCreationFailed": "Sem banco de dados e a criação falhou! Script encerrando!", "mismatchedLink": "Link não corresponde, por favor, atualize a página!", "startUpdatingConversationTree": "Começando a atualizar a árvore de conversa", "selectedItem": "Você selecionou {item}", "successSavingChanges": "Alterações salvas com sucesso!", "codeCopiedToClipboard": "Código copiado para a área de transferência!", "contentCopied": "Conteúdo copiado!", "emptyCommentPrompt": "O comentário está vazio. Você quer definir o comentário como \\"vazio\\"?", "confirmDeleteLinkData": "O link detectado é {item}! Tem certeza de que deseja excluir as informações deste link? Todo o conteúdo da conversa e os comentários serão excluídos!", "confirmCurrentURL": "O link detectado é {item}! Confirma?", "commentSetToEmpty": "O comentário foi definido como \\"vazio\\"", "enterCommentFirst": "Por favor, insira um comentário primeiro", "commentSaved": "Comentário salvo", "conversationDataDeleted": "Dados da conversa excluídos com sucesso", "executeSearchWithQuery": "Executar pesquisa: {item}", "searchPlaceholder": "Digite palavras-chave...", "searchButton": "Pesquisar", "searchInContent": "No conteúdo da conversa", "searchInComments": "Nos comentários do usuário", "searchInBoth": "Em conteúdo e comentários", "goToPrevious": "Ir para o anterior", "goToNext": "Ir para o próximo", "numberOfMatches": "{matches} correspondências", "nodeDetails": "Detalhes", "enterComment": "Digite um comentário", "userCommentSave": "Salvar", "userCommentCancel": "Cancelar", "userCommentClear": "Limpar" }, "ro": { "chatTreeRunning": "🥳🌳ChatTree🌳 este în funcțiune!🎉", "updateCurrentConversationTree": "🌈 Actualizați arborele conversației curente 🌈", "adjustBackgroundColorAndOpacity": "🎨 Ajustați culoarea de fundal și opacitatea 🎨", "toggleConversationTree": "🌳 Afișați/Ascundeți arborele conversației 🌳", "noDatabaseAndCreationFailed": "Nu există bază de date și crearea a eșuat! Scriptul se închide!", "mismatchedLink": "Link-ul nu se potrivește, vă rugăm să reîmprospătați pagina!", "startUpdatingConversationTree": "Începeți să actualizați arborele conversației", "selectedItem": "Ați selectat {item}", "successSavingChanges": "Modificările au fost salvate cu succes!", "codeCopiedToClipboard": "Codul a fost copiat în clipboard!", "contentCopied": "Conținutul a fost copiat!", "emptyCommentPrompt": "Comentariul este gol. Doriți să setați comentariul ca \\"gol\\"?", "confirmDeleteLinkData": "Link detectat ca fiind {item}! Confirmați ștergerea informațiilor acestui link? Tot conținutul conversației și comentariile vor fi șterse!", "confirmCurrentURL": "Link detectat ca fiind {item}! Confirmați?", "commentSetToEmpty": "Comentariu setat ca \\"gol\\"", "enterCommentFirst": "Vă rugăm să introduceți mai întâi un comentariu", "commentSaved": "Comentariu salvat", "conversationDataDeleted": "Datele conversației au fost șterse cu succes", "executeSearchWithQuery": "Executați căutarea: {item}", "searchPlaceholder": "Introduceți cuvinte cheie...", "searchButton": "Căutare", "searchInContent": "În conținutul conversației", "searchInComments": "În comentariile utilizatorului", "searchInBoth": "În conținut și comentarii", "goToPrevious": "Mergi la precedentul", "goToNext": "Mergi la următorul", "numberOfMatches": "{matches} potriviri", "nodeDetails": "Detalii", "enterComment": "Introduceți un comentariu", "userCommentSave": "Salvați", "userCommentCancel": "Anulați", "userCommentClear": "Șterge" }, "ru": { "chatTreeRunning": "🥳🌳ChatTree🌳 запущен!🎉", "updateCurrentConversationTree": "🌈 Обновить текущее дерево беседы 🌈", "adjustBackgroundColorAndOpacity": "🎨 Настроить цвет фона и прозрачность 🎨", "toggleConversationTree": "🌳 Показать/Скрыть дерево беседы 🌳", "noDatabaseAndCreationFailed": "База данных отсутствует, и создание не удалось! Скрипт выходит!", "mismatchedLink": "Ссылка не совпадает, пожалуйста, обновите страницу!", "startUpdatingConversationTree": "Начать обновление дерева беседы", "selectedItem": "Вы выбрали {item}", "successSavingChanges": "Изменения успешно сохранены!", "codeCopiedToClipboard": "Код скопирован в буфер обмена!", "contentCopied": "Содержимое скопировано!", "emptyCommentPrompt": "Комментарий пуст. Вы хотите установить комментарий как \\"пустой\\"?", "confirmDeleteLinkData": "Обнаружена ссылка {item}! Подтвердить удаление информации этой ссылки? Весь контент беседы и комментарии будут удалены!", "confirmCurrentURL": "Обнаружена ссылка {item}! Подтвердить?", "commentSetToEmpty": "Комментарий установлен как \\"пустой\\"", "enterCommentFirst": "Пожалуйста, сначала введите комментарий", "commentSaved": "Комментарий сохранен", "conversationDataDeleted": "Данные беседы успешно удалены", "executeSearchWithQuery": "Выполнить поиск: {item}", "searchPlaceholder": "Введите ключевые слова...", "searchButton": "Поиск", "searchInContent": "В контенте диалога", "searchInComments": "В комментариях пользователя", "searchInBoth": "В контенте и комментариях", "goToPrevious": "Перейти к предыдущему", "goToNext": "Перейти к следующему", "numberOfMatches": "{matches} совпадений", "nodeDetails": "Подробности", "enterComment": "Введите комментарий", "userCommentSave": "Сохранить", "userCommentCancel": "Отмена", "userCommentClear": "Очистить" }, "sk": { "chatTreeRunning": "🥳🌳ChatTree🌳 beží!🎉", "updateCurrentConversationTree": "🌈 Aktualizovať aktuálny konverzačný strom 🌈", "adjustBackgroundColorAndOpacity": "🎨 Upraviť farbu pozadia a priehľadnosť 🎨", "toggleConversationTree": "🌳 Zobraziť/Skryť konverzačný strom 🌳", "noDatabaseAndCreationFailed": "Nie je databáza a vytvorenie zlyhalo! Skript končí!", "mismatchedLink": "Odkaz sa nezhoduje, prosím, obnovte stránku!", "startUpdatingConversationTree": "Začať aktualizovať konverzačný strom", "selectedItem": "Vybrali ste {item}", "successSavingChanges": "Zmeny boli úspešne uložené!", "codeCopiedToClipboard": "Kód bol skopírovaný do schránky!", "contentCopied": "Obsah bol skopírovaný!", "emptyCommentPrompt": "Komentár je prázdny. Chcete nastaviť komentár na \\"prázdny\\"?", "confirmDeleteLinkData": "Odkaz detekovaný ako {item}! Potvrdiť odstránenie informácií tohto odkazu? Všetok obsah konverzácie a komentáre budú odstránené!", "confirmCurrentURL": "Odkaz detekovaný ako {item}! Potvrdiť?", "commentSetToEmpty": "Komentár bol nastavený na \\"prázdny\\"", "enterCommentFirst": "Najprv prosím, zadajte komentár", "commentSaved": "Komentár bol uložený", "conversationDataDeleted": "Dáta konverzácie boli úspešne odstránené", "executeSearchWithQuery": "Vykonať vyhľadávanie: {item}", "searchPlaceholder": "Zadajte kľúčové slová pre vyhľadávanie...", "searchButton": "Hľadať", "searchInContent": "V obsahu konverzácie", "searchInComments": "V komentároch", "searchInBoth": "V obsahu a komentároch", "goToPrevious": "Prejsť na predchádzajúci", "goToNext": "Prejsť na ďalší", "numberOfMatches": "{matches} zhôd", "nodeDetails": "Detaily", "enterComment": "Zadajte komentár", "userCommentSave": "Uložiť", "userCommentCancel": "Zrušiť", "userCommentClear": "Vymazať" }, "sr": { "chatTreeRunning": "🥳🌳ChatTree🌳 je pokrenut!🎉", "updateCurrentConversationTree": "🌈 Ažurirajte trenutno stablo razgovora 🌈", "adjustBackgroundColorAndOpacity": "🎨 Podesite boju pozadine i providnost 🎨", "toggleConversationTree": "🌳 Prikaži/Sakrij stablo razgovora 🌳", "noDatabaseAndCreationFailed": "Nema baze podataka, a kreiranje nije uspelo! Skript izlazi!", "mismatchedLink": "Link se ne podudara, molimo osvežite stranicu!", "startUpdatingConversationTree": "Počnite ažurirati stablo razgovora", "selectedItem": "Izabrali ste {item}", "successSavingChanges": "Promene su uspešno sačuvane!", "codeCopiedToClipboard": "Kod je kopiran u klipbord!", "contentCopied": "Sadržaj je kopiran!", "emptyCommentPrompt": "Komentar je prazan. Da li želite postaviti komentar kao \\"prazan\\"?", "confirmDeleteLinkData": "Link je detektovan kao {item}! Potvrditi brisanje informacija o ovom linku? Svi podaci razgovora i komentari će biti obrisani!", "confirmCurrentURL": "Link je detektovan kao {item}! Potvrditi?", "commentSetToEmpty": "Komentar je postavljen kao \\"prazan\\"", "enterCommentFirst": "Molimo prvo unesite komentar", "commentSaved": "Komentar je sačuvan", "conversationDataDeleted": "Podaci razgovora su uspešno obrisani", "executeSearchWithQuery": "Izvršiti pretragu: {item}", "searchPlaceholder": "Unesite ključne reči za pretragu...", "searchButton": "Pretraga", "searchInContent": "U sadržaju razgovora", "searchInComments": "U komentarima", "searchInBoth": "U sadržaju i komentarima", "goToPrevious": "Idi na prethodni", "goToNext": "Idi na sledeći", "numberOfMatches": "{matches} poklapanja", "nodeDetails": "Detalji", "enterComment": "Unesite komentar", "userCommentSave": "Sačuvaj", "userCommentCancel": "Otkaži", "userCommentClear": "Obriši" }, "sv": { "chatTreeRunning": "🥳🌳ChatTree🌳 är igång!🎉", "updateCurrentConversationTree": "🌈 Uppdatera aktuellt konversations träd 🌈", "adjustBackgroundColorAndOpacity": "🎨 Justera bakgrundsfärg och opacitet 🎨", "toggleConversationTree": "🌳 Visa/Dölj konversationsträd 🌳", "noDatabaseAndCreationFailed": "Ingen databas, och skapandet misslyckades! Skriptet avslutas!", "mismatchedLink": "Länken matchar inte, vänligen uppdatera sidan!", "startUpdatingConversationTree": "Börja uppdatera konversationsträdet", "selectedItem": "Du valde {item}", "successSavingChanges": "Ändringar sparade framgångsrikt!", "codeCopiedToClipboard": "Koden har kopierats till urklipp!", "contentCopied": "Innehållet har kopierats!", "emptyCommentPrompt": "Kommentaren är tom. Vill du ställa in kommentaren som \\"tom\\"?", "confirmDeleteLinkData": "Länk identifierad som {item}! Bekräfta radering av denna länks information? All konversationsinnehåll och kommentarer kommer att raderas!", "confirmCurrentURL": "Länk identifierad som {item}! Bekräfta?", "commentSetToEmpty": "Kommentaren är inställd på \\"tom\\"", "enterCommentFirst": "Vänligen skriv en kommentar först", "commentSaved": "Kommentar sparad", "conversationDataDeleted": "Konversationsdata har raderats framgångsrikt", "executeSearchWithQuery": "Utför sökning: {item}", "searchPlaceholder": "Ange sökord...", "searchButton": "Sök", "searchInContent": "I konversationsinnehållet", "searchInComments": "I kommentarer", "searchInBoth": "I både innehåll och kommentarer", "goToPrevious": "Gå till föregående", "goToNext": "Gå till nästa", "numberOfMatches": "{matches} träffar", "nodeDetails": "Detaljer", "enterComment": "Ange en kommentar", "userCommentSave": "Spara", "userCommentCancel": "Avbryt", "userCommentClear": "Rensa" }, "th": { "chatTreeRunning": "🥳🌳ChatTree🌳กำลังทำงาน!🎉", "updateCurrentConversationTree": "🌈 อัปเดตต้นไม้การสนทนาปัจจุบัน 🌈", "adjustBackgroundColorAndOpacity": "🎨 ปรับสีพื้นหลังและความโปร่งใส 🎨", "toggleConversationTree": "🌳 แสดง/ซ่อนต้นไม้การสนทนา 🌳", "noDatabaseAndCreationFailed": "ไม่มีฐานข้อมูล และไม่สามารถสร้างสำเร็จ! สคริปต์ออก!", "mismatchedLink": "ลิงก์ไม่ตรงกัน โปรดรีเฟรชหน้า!", "startUpdatingConversationTree": "เริ่มต้นอัปเดตต้นไม้การสนทนา", "selectedItem": "คุณเลือก {item}", "successSavingChanges": "บันทึกการเปลี่ยนแปลงสำเร็จ!", "codeCopiedToClipboard": "คัดลอกโค้ดไปยังคลิปบอร์ดแล้ว!", "contentCopied": "คัดลอกเนื้อหาแล้ว!", "emptyCommentPrompt": "คอมเมนต์ว่างเปล่า คุณต้องการตั้งค่าคอมเมนต์เป็น \\"ว่างเปล่า\\" หรือไม่?", "confirmDeleteLinkData": "ตรวจพบลิงก์เป็น {item}! ยืนยันที่จะลบข้อมูลลิงก์นี้หรือไม่? ข้อมูลการสนทนาและคอมเมนต์ทั้งหมดจะถูกลบ!", "confirmCurrentURL": "ตรวจพบลิงก์เป็น {item}! ยืนยันหรือไม่?", "commentSetToEmpty": "ตั้งค่าคอมเมนต์เป็น \\"ว่างเปล่า\\"", "enterCommentFirst": "โปรดใส่คอมเมนต์ก่อน", "commentSaved": "บันทึกคอมเมนต์แล้ว", "conversationDataDeleted": "ลบข้อมูลการสนทนาสำเร็จ", "executeSearchWithQuery": "ดำเนินการค้นหา: {item}", "searchPlaceholder": "ป้อนคำค้นหา...", "searchButton": "ค้นหา", "searchInContent": "ในเนื้อหาการสนทนา", "searchInComments": "ในความคิดเห็น", "searchInBoth": "ทั้งเนื้อหาและความคิดเห็น", "goToPrevious": "ไปที่ก่อนหน้า", "goToNext": "ไปที่ถัดไป", "numberOfMatches": "{matches} รายการที่ตรงกัน", "nodeDetails": "รายละเอียด", "enterComment": "กรุณาใส่ความคิดเห็น", "userCommentSave": "บันทึก", "userCommentCancel": "ยกเลิก", "userCommentClear": "ล้าง" }, "tr": { "chatTreeRunning": "🥳🌳ChatTree🌳Çalışıyor!🎉", "updateCurrentConversationTree": "🌈 Güncel Konuşma Ağacını Güncelle 🌈", "adjustBackgroundColorAndOpacity": "🎨 Arka Plan Rengini ve Şeffaflığı Ayarla 🎨", "toggleConversationTree": "🌳 Konuşma Ağacını Göster/Gizle 🌳", "noDatabaseAndCreationFailed": "Veritabanı yok ve oluşturulamadı! Betik çıkıyor!", "mismatchedLink": "Bağlantı eşleşmiyor, lütfen sayfayı yenileyin!", "startUpdatingConversationTree": "Konuşma Ağacını Güncellemeye Başla", "selectedItem": "{item} seçildi", "successSavingChanges": "Değişiklikler Başarıyla Kaydedildi!", "codeCopiedToClipboard": "Kod panoya kopyalandı!", "contentCopied": "İçerik kopyalandı!", "emptyCommentPrompt": "Yorum boş. Yorumu \\"boş\\" olarak ayarlamak istiyor musunuz?", "confirmDeleteLinkData": "{item} bağlantısı tespit edildi! Bu bağlantının bilgilerini silmek istediğinizi onaylıyor musunuz? Tüm konuşma ve yorum içerikleri silinecek!", "confirmCurrentURL": "{item} bağlantısı tespit edildi! Onaylıyor musunuz?", "commentSetToEmpty": "Yorum \\"boş\\" olarak ayarlandı", "enterCommentFirst": "Lütfen önce bir yorum girin", "commentSaved": "Yorum kaydedildi", "conversationDataDeleted": "Konuşma Verileri Başarıyla Silindi", "executeSearchWithQuery": "Arama Yapılıyor: {item}", "searchPlaceholder": "Arama anahtar kelimelerini girin...", "searchButton": "Ara", "searchInContent": "Konuşma İçeriğinde", "searchInComments": "Yorumlarda", "searchInBoth": "İçerik ve Yorumlarda", "goToPrevious": "Öncekine Git", "goToNext": "Sonrakine Git", "numberOfMatches": "{matches} eşleşme", "nodeDetails": "Detaylar", "enterComment": "Bir yorum girin", "userCommentSave": "Kaydet", "userCommentCancel": "İptal", "userCommentClear": "Temizle" }, "uk": { "chatTreeRunning": "🥳🌳ChatTree🌳в роботі!🎉", "updateCurrentConversationTree": "🌈 Оновити поточне дерево розмов 🌈", "adjustBackgroundColorAndOpacity": "🎨 Налаштувати колір фону та прозорість 🎨", "toggleConversationTree": "🌳 Показати/сховати дерево розмов 🌳", "noDatabaseAndCreationFailed": "Немає бази даних, і не вдалося створити! Скрипт виходить!", "mismatchedLink": "Посилання не збігається, будь ласка, оновіть сторінку!", "startUpdatingConversationTree": "Почати оновлення дерева розмов", "selectedItem": "Ви обрали {item}", "successSavingChanges": "Зміни успішно збережено!", "codeCopiedToClipboard": "Код скопійовано в буфер обміну!", "contentCopied": "Зміст скопійовано!", "emptyCommentPrompt": "Коментар порожній. Ви хочете встановити коментар як \\"порожній\\"?", "confirmDeleteLinkData": "Посилання виявлене як {item}! Підтверджуєте видалення цього посилання? Всі дані розмов і коментарі будуть видалені!", "confirmCurrentURL": "Посилання виявлене як {item}! Підтвердити?", "commentSetToEmpty": "Коментар встановлено як \\"порожній\\"", "enterCommentFirst": "Будь ласка, спочатку введіть коментар", "commentSaved": "Коментар збережено", "conversationDataDeleted": "Дані розмови успішно видалено", "executeSearchWithQuery": "Виконати пошук: {item}", "searchPlaceholder": "Введіть ключові слова для пошуку...", "searchButton": "Пошук", "searchInContent": "У вмісті розмови", "searchInComments": "У коментарях", "searchInBoth": "У вмісті та коментарях", "goToPrevious": "Перейти до попереднього", "goToNext": "Перейти до наступного", "numberOfMatches": "{matches} збігів", "nodeDetails": "Деталі", "enterComment": "Введіть коментар", "userCommentSave": "Зберегти", "userCommentCancel": "Скасувати", "userCommentClear": "Очистити" }, "ug": { "chatTreeRunning": "🥳🌳ChatTree🌳ئىشلىتىلىۋاتىدۇ!🎉", "updateCurrentConversationTree": "🌈 نۆۋەتتىكي سۆھبەت تەرەككىنى يېڭىلاڭ 🌈", "adjustBackgroundColorAndOpacity": "🎨 فون رەڭگىنى ۋە شېفافلىقىنى تەڭشەڭ 🎨", "toggleConversationTree": "🌳 سۆھبەت تەرەككىنى كۆرسىتىش/يوشۇرۇش 🌳", "noDatabaseAndCreationFailed": "ماڭلىق يوق، ھەمدە قۇرۇلمىدى! سكرىپت چىقىدۇ!", "mismatchedLink": "ئۇلىنىش ماس كەلمىدى، تور بەتنى يېڭىلاڭ!", "startUpdatingConversationTree": "سۆھبەت تەرەككىنى يېڭىلاشنى باشلاڭ", "selectedItem": "سىز تاللىغان {item}", "successSavingChanges": "ئۆزگەرتىشنى ساقلاش مۇۋەپپەقىيەتلىك بولدى!", "codeCopiedToClipboard": "كود تەسۋىرلىتىش تاختىسىغا كۆچۈرۈلدى!", "contentCopied": "مەزمۇن كۆچۈرۈلدى!", "emptyCommentPrompt": "ئىزاھات قۇرۇق. \\"قۇرۇق\\" دەپ بەلگىلەمسىز؟", "confirmDeleteLinkData": "{item} ئۇلىنىش تەپلىگەن! بۇ ئۇلىنىشنىڭ ئۇچۇرىنى ئۆچۈرۈشنى جەزملەسىزمۇ؟ بارلىق سۆھبەت ۋە ئىزاھات ئۆچۈرۈلىدۇ!", "confirmCurrentURL": "{item} ئۇلىنىش تەپلىگەن! جەزملەسىزمۇ؟", "commentSetToEmpty": "ئىزاھات \\"قۇرۇق\\" دەپ بەلگىلەندى", "enterCommentFirst": "ئاۋۋال ئىزاھات كىرگۈزۈڭ", "commentSaved": "ئىزاھات ساقلاندى", "conversationDataDeleted": "سۆھبەت ئۇچۇرى مۇۋەپپەقىيەتلىك ئۆچۈرۈلدى", "executeSearchWithQuery": "ئىزدەشنى ئىجرا قىلىدۇ: {item}", "searchPlaceholder": "ئىزدەش سۆزىنى كىرگۈزۈڭ...", "searchButton": "ئىزدەش", "searchInContent": "سۆھبەت مەزمۇنىدا", "searchInComments": "ئىزاھاتتا", "searchInBoth": "مەزمۇن ۋە ئىزاھاتتا", "goToPrevious": "ئالدىنقىغا بېرىش", "goToNext": "كېيىنكىگە بېرىش", "numberOfMatches": "{matches} دەسلەپتىكى ئۇنۇم", "nodeDetails": "نود تەپسىلاتى", "enterComment": "ئىزاھات كىرگۈزۈڭ", "userCommentSave": "ساقلا", "userCommentCancel": "بىكار قىل", "userCommentClear": "تازىلا" }, "vi": { "chatTreeRunning": "🥳🌳ChatTree🌳đang chạy!🎉", "updateCurrentConversationTree": "🌈 Cập nhật cây trò chuyện hiện tại 🌈", "adjustBackgroundColorAndOpacity": "🎨 Điều chỉnh màu nền và độ mờ 🎨", "toggleConversationTree": "🌳 Hiển thị/Ẩn cây trò chuyện 🌳", "noDatabaseAndCreationFailed": "Không có cơ sở dữ liệu và không thể tạo được! Script thoát!", "mismatchedLink": "Liên kết không khớp, vui lòng làm mới trang!", "startUpdatingConversationTree": "Bắt đầu cập nhật cây trò chuyện", "selectedItem": "Bạn đã chọn {item}", "successSavingChanges": "Lưu thay đổi thành công!", "codeCopiedToClipboard": "Mã đã được sao chép vào bảng tạm!", "contentCopied": "Nội dung đã được sao chép!", "emptyCommentPrompt": "Bình luận trống. Bạn có muốn đặt bình luận thành \\"trống\\" không?", "confirmDeleteLinkData": "Đã phát hiện liên kết là {item}! Bạn có chắc chắn muốn xóa thông tin của liên kết này không? Tất cả nội dung trò chuyện và bình luận sẽ bị xóa!", "confirmCurrentURL": "Đã phát hiện liên kết là {item}! Bạn có xác nhận không?", "commentSetToEmpty": "Bình luận đã được đặt thành \\"trống\\"", "enterCommentFirst": "Vui lòng nhập bình luận trước", "commentSaved": "Bình luận đã được lưu", "conversationDataDeleted": "Dữ liệu trò chuyện đã được xóa thành công", "executeSearchWithQuery": "Thực hiện tìm kiếm: {item}", "searchPlaceholder": "Nhập từ khóa tìm kiếm...", "searchButton": "Tìm kiếm", "searchInContent": "Trong nội dung cuộc trò chuyện", "searchInComments": "Trong bình luận", "searchInBoth": "Cả trong nội dung và bình luận", "goToPrevious": "Đi đến trước đó", "goToNext": "Đi đến tiếp theo", "numberOfMatches": "{matches} kết quả phù hợp", "nodeDetails": "Chi tiết nút", "enterComment": "Nhập bình luận", "userCommentSave": "Lưu", "userCommentCancel": "Hủy", "userCommentClear": "Xóa sạch" }, "zh": { "chatTreeRunning": "🥳🌳ChatTree🌳运行中!🎉", "updateCurrentConversationTree": "🌈 更新当前对话树 🌈", "adjustBackgroundColorAndOpacity": "🎨 调整背景颜色和透明度 🎨", "toggleConversationTree": "🌳 显示/隐藏对话树 🌳", "noDatabaseAndCreationFailed": "没有数据库,并且未能成功创建!脚本退出!", "mismatchedLink": "链接不匹配,请刷新页面!", "startUpdatingConversationTree": "开始更新对话树", "selectedItem": "您选择了{item}", "successSavingChanges": "更改保存成功!", "codeCopiedToClipboard": "代码已复制到剪贴板!", "contentCopied": "内容已复制!", "emptyCommentPrompt": "注释为空。是否将注释设置为\\"空\\"?", "confirmDeleteLinkData": "监测到链接为 {item}!确认要删除这个链接的信息吗?所有的对话内容和注释都将被删除!", "confirmCurrentURL": "监测到链接为 {item}!确认吗?", "commentSetToEmpty": "注释已设置为\\"空\\"", "enterCommentFirst": "请先输入注释内容", "commentSaved": "注释已保存", "conversationDataDeleted": "对话数据成功删除", "executeSearchWithQuery": "执行搜索:{item}", "searchPlaceholder": "输入搜索关键词...", "searchButton": "搜索", "searchInContent": "对话内容", "searchInComments": "用户注释", "searchInBoth": "内容与注释", "goToPrevious": "转到上一个", "goToNext": "转到下一个", "numberOfMatches": "{matches} 个匹配项", "nodeDetails": "详情", "enterComment": "请输入注释", "userCommentSave": "保存", "userCommentCancel": "取消", "userCommentClear": "清空" }, "zh-CN": { "chatTreeRunning": "🥳🌳ChatTree🌳运行中!🎉", "updateCurrentConversationTree": "🌈 更新当前对话树 🌈", "adjustBackgroundColorAndOpacity": "🎨 调整背景颜色和透明度 🎨", "toggleConversationTree": "🌳 显示/隐藏对话树 🌳", "noDatabaseAndCreationFailed": "没有数据库,并且未能成功创建!脚本退出!", "mismatchedLink": "链接不匹配,请刷新页面!", "startUpdatingConversationTree": "开始更新对话树", "selectedItem": "您选择了{item}", "successSavingChanges": "更改保存成功!", "codeCopiedToClipboard": "代码已复制到剪贴板!", "contentCopied": "内容已复制!", "emptyCommentPrompt": "注释为空。是否将注释设置为\\"空\\"?", "confirmDeleteLinkData": "监测到链接为 {item}!确认要删除这个链接的信息吗?所有的对话内容和注释都将被删除!", "confirmCurrentURL": "监测到链接为 {item}!确认吗?", "commentSetToEmpty": "注释已设置为\\"空\\"", "enterCommentFirst": "请先输入注释内容", "commentSaved": "注释已保存", "conversationDataDeleted": "对话数据成功删除", "executeSearchWithQuery": "执行搜索:{item}", "searchPlaceholder": "输入搜索关键词...", "searchButton": "搜索", "searchInContent": "对话内容", "searchInComments": "用户注释", "searchInBoth": "内容与注释", "goToPrevious": "转到上一个", "goToNext": "转到下一个", "numberOfMatches": "{matches} 个匹配项", "nodeDetails": "详情", "enterComment": "请输入注释", "userCommentSave": "保存", "userCommentCancel": "取消", "userCommentClear": "清空" }, "zh-TW": { "chatTreeRunning": "🥳🌳ChatTree🌳運行中!🎉", "updateCurrentConversationTree": "🌈 更新當前對話樹 🌈", "adjustBackgroundColorAndOpacity": "🎨 調整背景顏色和透明度 🎨", "toggleConversationTree": "🌳 顯示/隱藏對話樹 🌳", "noDatabaseAndCreationFailed": "沒有資料庫,且未能成功創建!腳本退出!", "mismatchedLink": "鏈接不匹配,請刷新頁面!", "startUpdatingConversationTree": "開始更新對話樹", "selectedItem": "您選擇了{item}", "successSavingChanges": "更改保存成功!", "codeCopiedToClipboard": "代碼已複製到剪貼板!", "contentCopied": "內容已複製!", "emptyCommentPrompt": "註釋為空。是否將註釋設置為\\"空\\"?", "confirmDeleteLinkData": "監測到鏈接為 {item}!確認要刪除這個鏈接的信息嗎?所有的對話內容和註釋都將被刪除!", "confirmCurrentURL": "監測到鏈接為 {item}!確認嗎?", "commentSetToEmpty": "註釋已設置為\\"空\\"", "enterCommentFirst": "請先輸入註釋內容", "commentSaved": "註釋已保存", "conversationDataDeleted": "對話數據成功刪除", "executeSearchWithQuery": "執行搜索:{item}", "searchPlaceholder": "輸入搜索關鍵詞...", "searchButton": "搜索", "searchInContent": "對話內容", "searchInComments": "使用者註釋", "searchInBoth": "內容與註釋", "goToPrevious": "轉到上一個", "goToNext": "轉到下一個", "numberOfMatches": "{matches} 個匹配項", "nodeDetails": "詳情", "enterComment": "請輸入注釋", "userCommentSave": "保存", "userCommentCancel": "取消", "userCommentClear": "清空" }, "zh-HK": { "chatTreeRunning": "🥳🌳ChatTree🌳運行中!🎉", "updateCurrentConversationTree": "🌈 更新當前對話樹 🌈", "adjustBackgroundColorAndOpacity": "🎨 調整背景顏色和透明度 🎨", "toggleConversationTree": "🌳 顯示/隱藏對話樹 🌳", "noDatabaseAndCreationFailed": "沒有資料庫,且未能成功創建!腳本退出!", "mismatchedLink": "鏈接不匹配,請刷新頁面!", "startUpdatingConversationTree": "開始更新對話樹", "selectedItem": "您選擇了{item}", "successSavingChanges": "更改保存成功!", "codeCopiedToClipboard": "代碼已複製到剪貼板!", "contentCopied": "內容已複製!", "emptyCommentPrompt": "註釋為空。是否將註釋設置為\\"空\\"?", "confirmDeleteLinkData": "監測到鏈接為 {item}!確認要刪除這個鏈接的信息嗎?所有的對話內容和註釋都將被刪除!", "confirmCurrentURL": "監測到鏈接為 {item}!確認嗎?", "commentSetToEmpty": "註釋已設置為\\"空\\"", "enterCommentFirst": "請先輸入註釋內容", "commentSaved": "註釋已保存", "conversationDataDeleted": "對話數據成功刪除", "executeSearchWithQuery": "執行搜索:{item}", "searchPlaceholder": "輸入搜尋關鍵詞...", "searchButton": "搜尋", "searchInContent": "對話內容", "searchInComments": "用戶註釋", "searchInBoth": "內容與註釋", "goToPrevious": "轉到上一個", "goToNext": "轉到下一個", "numberOfMatches": "{matches} 個匹配項", "nodeDetails": "詳情", "enterComment": "請輸入註釋", "userCommentSave": "儲存", "userCommentCancel": "取消", "userCommentClear": "清除" }, "zh-SG": { "chatTreeRunning": "🥳🌳ChatTree🌳运行中!🎉", "updateCurrentConversationTree": "🌈 更新当前对话树 🌈", "adjustBackgroundColorAndOpacity": "🎨 调整背景颜色和透明度 🎨", "toggleConversationTree": "🌳 显示/隐藏对话树 🌳", "noDatabaseAndCreationFailed": "没有数据库,并且未能成功创建!脚本退出!", "mismatchedLink": "链接不匹配,请刷新页面!", "startUpdatingConversationTree": "开始更新对话树", "selectedItem": "您选择了{item}", "successSavingChanges": "更改保存成功!", "codeCopiedToClipboard": "代码已复制到剪贴板!", "contentCopied": "内容已复制!", "emptyCommentPrompt": "注释为空。是否将注释设置为\\"空\\"?", "confirmDeleteLinkData": "监测到链接为 {item}!确认要删除这个链接的信息吗?所有的对话内容和注释都将被删除!", "confirmCurrentURL": "监测到链接为 {item}!确认吗?", "commentSetToEmpty": "注释已设置为\\"空\\"", "enterCommentFirst": "请先输入注释内容", "commentSaved": "注释已保存", "conversationDataDeleted": "对话数据成功删除", "executeSearchWithQuery": "执行搜索:{item}", "searchPlaceholder": "输入搜索关键词...", "searchButton": "搜索", "searchInContent": "对话内容", "searchInComments": "用户注释", "searchInBoth": "内容与注释", "goToPrevious": "转到上一个", "goToNext": "转到下一个", "numberOfMatches": "{matches} 个匹配项", "nodeDetails": "详情", "enterComment": "请输入注释", "userCommentSave": "保存", "userCommentCancel": "取消", "userCommentClear": "清空" } }`; lang = JSON.parse(lang); const userLang = navigator.languages.find(l => l in lang) || 'en'; //const userLang = 'vi'; //console.log("currentLang:",userLang); globalUserLang = userLang; return lang[userLang]; }; let globalUserLang; const currentLangPack = getLang(); //console.log("currentLangPack", currentLangPack); function translate(key) { return currentLangPack[key] || key; } const states = { mainButton: { isDragging: false, isMouseOver: false }, url: { isValidURL: false, url: '' }, treeUpdate: { isDOMOperating: false, }, visualization: { contentDiv: 0, thumbnailSvg: 0, } }; const DB_NAME = 'ChatTreeDB'; const CONVERSATIONS_STORE_NAME = 'conversations'; const SEARCH_HISTORY_STORE_NAME = 'searchHistory'; const USER_SETTINGS_STORE_NAME = 'userSettings'; let db; class DialogueNode { constructor(content, type) { this.content = content; this.type = type; this.uuid = generateUUID(); this.children = []; this.comment = ''; } } let conversationData = { url: null, rootNode: new DialogueNode("chatStartsHere", "chatGPT"), uuid2pathMap: new Map(), uuid2nodeMap: new Map(), path2nodeMap: new Map(), bookMarked: new Map(), timestamp: Date.now(), participants: { user: { name: "UserName", avatarURL: "UserAvatarURL", avatarHTML: "💕", }, gpt: { type: "GPT-3", } } }; let GPT_Avatar_Config = { gpt4_Inner_Html: "
", gpt3_Inner_Html: "", } let root, treeLayout, svg, svgThumbnail, defs, gLinks, gNodes, nodeDrag, canvasDrag, zoom, searchHistoryRecord, curMouseOnUUID = null; const waitForDomChange = (element) => { return new Promise(resolve => { const observer = new MutationObserver((mutationsList, observer) => { observer.disconnect(); resolve(); }); observer.observe(element, {childList: true, subtree: true}); }); }; function sleep(ms) { return new Promise(resolve => setTimeout(resolve, ms)); } const treeOperation = { initializeChatTree: async function () { if (!states.url.isValidURL) { ButtonOperations.showUserNotification(translate("mismatchedLink")); return; } states.treeUpdate.isDOMOperating = true; let operatingURL = states.url.url; const button = document.querySelector('button.flex.w-full.items-center.gap-3.rounded-md.px-3.py-3.text-sm[data-headlessui-state=""]'); if (button) { const relativeFlexElement = button.querySelector('.relative.flex'); if (relativeFlexElement) { conversationData.participants.user.avatarHTML = relativeFlexElement.innerHTML; const imgElement = relativeFlexElement.querySelector('img.rounded-sm'); if (imgElement) { const imgSrc = imgElement.getAttribute('src'); conversationData.participants.user.avatarURL = imgSrc; } else { log('Image Element Not Found'); } } else { log('Relative Flex Element Not Found'); } const fontSemiboldElement = button.querySelector('.font-semibold'); if (fontSemiboldElement) { conversationData.participants.user.name = fontSemiboldElement.innerHTML; } else { log('Font Semibold Element Not Found'); } } else { let allDivs = DOMOperations.getAllDivs(); if (allDivs) { let userDiv = allDivs[0]; const imageDiv = userDiv.querySelector('div.flex-shrink-0.flex.flex-col.relative.items-end'); if (imageDiv) { const relativeFlexElement = imageDiv.querySelector('.relative.flex'); if (relativeFlexElement) { conversationData.participants.user.avatarHTML = relativeFlexElement.innerHTML; const imgElement = relativeFlexElement.querySelector('img.rounded-sm'); if (imgElement) { const imgSrc = imgElement.getAttribute('src'); conversationData.participants.user.avatarURL = imgSrc; } else { log('Image Element Not Found'); } } else { log('Relative Flex Element Not Found'); } } } log('Button Element Not Found'); } let allDivs = DOMOperations.getAllDivs(); if (allDivs.length > 1) { const gptDiv = allDivs[1].querySelector('.relative.p-1.rounded-sm.h-9.w-9.text-white.flex.items-center.justify-center'); if (gptDiv) { const computedStyle = window.getComputedStyle(gptDiv); const bgColor = computedStyle.backgroundColor; log('Background Color:', bgColor); if (bgColor === 'rgb(171, 104, 255)') { conversationData.participants.gpt.type = 'GPT-4' } else if (bgColor === 'rgb(25, 195, 125)') { conversationData.participants.gpt.type = 'GPT-3' } else { log('The background color does not match.'); } } else { log('gptDiv not found'); } } log("url:", operatingURL); let result = DOMOperations.getButtonInfo(); let hasLeftButton = result.hasLeftButtonUnClicked; while (hasLeftButton) { if (states.url.url !== operatingURL || !states.treeUpdate.isDOMOperating) { log("监测到链接变换! 退出initializeChatTree 函数!"); states.treeUpdate.isDOMOperating = false; return; } let allChatDivs = DOMOperations.getAllDivs(); if (allChatDivs.length === 0) { log("监测到没有divs:退出初始化!"); states.treeUpdate.isDOMOperating = false; return; } let j = 0; for (; j < allChatDivs.length; j++) { if (result.childIndicesPath[j] !== 1) { DOMOperations.clickButtonAtDivLevel(0, j); log("clicking the ", j, "th div!"); await waitForDomChange(document.body); break; } } if (j === allChatDivs.length) { break; } result = DOMOperations.getButtonInfo(); log("result:", result); hasLeftButton = result.hasLeftButtonUnClicked; } log("Initializing Over."); await this.updateTree(operatingURL); }, //🤖chatGPT版本 updateTree: async function (url) { let allpaths = []; log("更新树"); let operatingURL = url; if (states.url.url !== operatingURL) { log("监测到链接变换! 退出initializeChatTree 函数!"); return; } let allChatDivs = DOMOperations.getAllDivs(); let hasRightButtonUnClicked = true; let curRootDivChoice = 0; while (hasRightButtonUnClicked) { if (states.url.url !== operatingURL || !states.treeUpdate.isDOMOperating) { log("监测到链接变换! 退出updateTree 函数!"); states.treeUpdate.isDOMOperating = false; return; } hasRightButtonUnClicked = false; allChatDivs = DOMOperations.getAllDivs(); if (allChatDivs.length === 0) { log("监测到没有divs:退出更新!"); states.treeUpdate.isDOMOperating = false; return; } let result = DOMOperations.getButtonInfo(); for (let i = curRootDivChoice; i < allChatDivs.length; i++) { if (states.url.url !== operatingURL || !states.treeUpdate.isDOMOperating) { log("监测到链接变换! 退出initializeChatTree 函数!"); states.treeUpdate.isDOMOperating = false; return; } let contentResult = DOMOperations.getTextContent(allChatDivs[i], i); let path = result.childIndicesPath.slice(0, i + 1); log("path", path, "content:", contentResult); let isExisting = conversationData.path2nodeMap.get(arrayToKey(path)); if (isExisting) { log("isExisting!", isExisting); log("contentResult.contentText", contentResult.contentText); if (isExisting.content === contentResult.contentText) { allpaths.push(arrayToKey(path)); continue; } else { isExisting.content = contentResult.contentText allpaths.push(arrayToKey(path)); continue; } } let father = i > 0 ? conversationData.path2nodeMap.get(arrayToKey(result.childIndicesPath.slice(0, i))) : conversationData.rootNode; let newDialogueNode = new DialogueNode(contentResult.contentText, contentResult.userType); log("father :", father); father.children.push(newDialogueNode); log("newDialogueNode:", newDialogueNode); log("dataRenewing:", conversationData); conversationData.uuid2pathMap.set(newDialogueNode.uuid, path); conversationData.uuid2nodeMap.set(newDialogueNode.uuid, newDialogueNode); conversationData.path2nodeMap.set(arrayToKey(path), newDialogueNode); log("father:", father); allpaths.push(arrayToKey(path)); } let curRootChoice = allChatDivs.length - 1; for (; curRootChoice >= 0; curRootChoice--) { if (url !== states.url.url) { log("发现url变化! 退出更新树"); states.treeUpdate.isDOMOperating = false; return; } if (result.childIndicesPath[curRootChoice] !== result.childrenCountPath[curRootChoice]) { DOMOperations.clickButtonAtDivLevel(1, curRootChoice); let ableToContinue = false; while (!ableToContinue) { await sleep(50); let result1 = DOMOperations.getButtonInfo(); let childIndecices = result1.childIndicesPath; if (childIndecices.length !== result.childIndicesPath.length) { ableToContinue = true; break; } for (let i = 0; i < childIndecices.length; i++) { if (childIndecices[i] !== result.childIndicesPath[i]) { ableToContinue = true; break; } } } curRootDivChoice = curRootChoice; hasRightButtonUnClicked = true; break; } } if (!hasRightButtonUnClicked) { log("所有的节点都加进来了!") log("准备保存的data:", conversationData); if (states.url.url !== operatingURL || window.location.href !== operatingURL) { log("监测到链接变化, 停止更新!"); states.treeUpdate.isDOMOperating = false; return; } try { await dbOperations.saveConversationsData(conversationData); await dbOperations.loadConversationsData(operatingURL); } catch (error) { console.error("Error:", error); } log("重新读取到的data:", conversationData); break; } } states.treeUpdate.isDOMOperating = false; }, jumpToDialogueItem: async function (uuid) { if (!uuid || !conversationData.uuid2pathMap.get(uuid) || uuid === conversationData.rootNode.uuid) { return; } let path = conversationData.uuid2pathMap.get(uuid); if (!path) { log("没有从map中获取路径! 请检查!") return; } let result = DOMOperations.getButtonInfo(); log("path:", path); let i = 0; while (i < path.length) { result = DOMOperations.getButtonInfo(); if (path[i] === result.childIndicesPath[i]) { i++; continue; } if (path[i] < result.childIndicesPath[i]) { DOMOperations.clickButtonAtDivLevel(0, i); log("path:", path); result = DOMOperations.getButtonInfo(); await sleep(200); continue; } if (path[i] > result.childIndicesPath[i]) { DOMOperations.clickButtonAtDivLevel(1, i); log("path:", path); result = DOMOperations.getButtonInfo(); await sleep(200); continue; } } let j = 0; for (; j < path.length; j++) { if (path[j] !== result.childIndicesPath[j]) { log("在:", j, "没有成功转到!"); log(path, result.childIndicesPath); break; } } sleep(200); if (j === path.length) { let allDivs = DOMOperations.getAllDivs(); log("path", path, "result.childIndicesPath", result.childIndicesPath, "allDivs[path.length - 1]", allDivs[path.length - 1]); function highlightDiv1() { allDivs[path.length - 1].classList.add('highlight'); setTimeout(() => { allDivs[path.length - 1].classList.remove('highlight'); }, 4000); } function highlightDiv2() { allDivs[path.length - 1].classList.add('highlightt'); setTimeout(() => { allDivs[path.length - 1].classList.remove('highlightt'); }, 4000); } function blinkText() { allDivs[path.length - 1].classList.add('blinkText'); setTimeout(() => { allDivs[path.length - 1].classList.remove('blinkText'); }, 5000); } allDivs[path.length - 1].scrollIntoView({behavior: 'smooth', block: 'center', inline: 'start'}); const htmlClass = document.documentElement.getAttribute('class'); if (htmlClass && htmlClass.includes('dark')) { highlightDiv1(); } else { highlightDiv2(); } setTimeout(() => { allDivs[path.length - 1].scrollIntoView({behavior: 'smooth', block: 'center', inline: 'start'}); const htmlClass = document.documentElement.getAttribute('class'); if (htmlClass && htmlClass.includes('dark')) { highlightDiv1(); } else { highlightDiv2(); } }, 1000); log("成功转到!"); } }, }; const urlOperations = { getCurrentURL: function () { return window.location.href; }, isValidURL: function (url) { const pattern = /^https:\/\/chat\.openai\.com\/c\/[a-z0-9\-]+\/?$/; return pattern.test(url); }, isNonUniqueURL: function (url) { const nonUniquePatterns = [ /^https:\/\/chat\.openai\.com\/?$/, /^https:\/\/chat\.openai\.com\/\?model=.+$/ ]; return nonUniquePatterns.some(pattern => pattern.test(url)); }, getCurURLInfo: function () { let curURL = window.location.href; let isCurURLValid = this.isValidURL(curURL); let isCurURLUnique = !this.isNonUniqueURL(curURL); return { curURL: curURL, isCurURLValid: isCurURLValid, isCurURLUnique: isCurURLUnique, }; }, observeTargetChanges: function () { let lastURL = window.location.href; if (urlOperations.isValidURL(lastURL)) { urlOperations.handleURLChange(lastURL); states.url.url = window.location.href; states.url.isValidURL = true; } function callback(mutationsList, observer) { const currentURL = window.location.href; log("currentURL:", currentURL); if (urlOperations.isValidURL(currentURL)) { if (currentURL !== lastURL) { log("URL changed:", currentURL); lastURL = currentURL; urlOperations.handleURLChange(currentURL); states.treeUpdate.isDOMOperating = false; } else { log("Current URL:", currentURL); } } else if (urlOperations.isNonUniqueURL(currentURL)) { log("Non-unique URL:", currentURL, " detected. Please refresh the page."); urlOperations.handleURLChange(currentURL); } }; let outter_observer; let inner_observer; let curState = null; const startObserving = (target, config, callback, observer) => { if (observer) { observer.disconnect(); } observer = new MutationObserver(callback); observer.observe(target, config); log('Started observing:', target); return observer; }; window.addEventListener("resize", function () { checkCurrentState(); }); const checkCurrentState = () => { const flexDiv = document.querySelector('.flex-shrink-0.overflow-x-hidden.dark.bg-gray-900'); const htmlTag = document.querySelector('html'); if (flexDiv && curState !== 1) { log('Switched to State 1.'); curState = 1; const config = {attributes: true, attributeFilter: ['style']}; outter_observer = startObserving(htmlTag, config, (mutations) => { if (mutations.some(m => m.type === 'attributes' && m.attributeName === 'style')) { log('HTML style changed.'); checkCurrentState(); } }, outter_observer); const innerConfig = {childList: true, subtree: true}; inner_observer = startObserving(flexDiv, innerConfig, (mutations) => { if (mutations.some(m => m.type === 'childList')) { log('FlexDiv child list changed.'); callback(); checkCurrentState(); } }, inner_observer); } else if (!flexDiv && curState !== 2) { log('Switched to State 2.'); curState = 2; const config = {childList: true, subtree: true}; outter_observer = startObserving(document.body, config, (mutations) => { if (mutations.some(m => m.type === 'childList')) { log('Body child list changed.'); const conversationList = document.querySelector('#headlessui-portal-root'); if (conversationList) { log('Conversation List Detected.'); inner_observer = startObserving(conversationList, config, (mutations) => { if (mutations.some(m => m.type === 'childList')) { log('Conversation List child list changed.'); callback(); } }, inner_observer); } checkCurrentState(); } }, outter_observer); } }; checkCurrentState(); }, handleURLChange: function (url) { log("In handleURLChange, Data:", conversationData); if (urlOperations.isNonUniqueURL(url)) { states.url.isValidURL = false; states.url.url = ''; states.treeUpdate.isDOMOperating = false; conversationData = { url: null, rootNode: new DialogueNode("chatStartsHere", "chatGPT"), uuid2pathMap: new Map(), uuid2nodeMap: new Map(), path2nodeMap: new Map(), bookMarked: new Map(), timestamp: Date.now(), participants: { user: { name: "UserName", avatarURL: "UserAvatarURL", avatarHTML: "User", }, gpt: { type: "GPT-3", } } }; root = d3.hierarchy(conversationData.rootNode); const widthPerNode = 30; const heightPerNode = 30; treeLayout = d3.tree().nodeSize([widthPerNode, heightPerNode]); treeLayout(root); settingsKit.refreshTree(); log("请刷新页面或者转到具有对话信息的页面从而获取正确的链接"); } else { states.url.isValidURL = true; states.url.url = url; dbOperations.loadConversationsData(url).then(loadeddata => { log("Loaded data for URL:", loadeddata); conversationData = loadeddata; root = d3.hierarchy(conversationData.rootNode); const widthPerNode = 30; const heightPerNode = 30; treeLayout = d3.tree().nodeSize([widthPerNode, heightPerNode]); treeLayout(root); settingsKit.refreshTree(); }).catch(error => { console.error("Error loading data:", error); }); } } }; let GlobalMainTreeBtnColorSettings = {}; let GlobalMainTreeBtnPositionSettings = {}; const dbOperations = { initDatabase: function () { return new Promise((resolve, reject) => { const request = indexedDB.open(DB_NAME, 1); request.onerror = event => { console.error("Detailed Error:", event); reject("Error opening database:", event); }; request.onupgradeneeded = event => { log("升级数据库!"); db = event.target.result; if (!db.objectStoreNames.contains(CONVERSATIONS_STORE_NAME)) { db.createObjectStore(CONVERSATIONS_STORE_NAME, {keyPath: "url"}); } if (!db.objectStoreNames.contains(SEARCH_HISTORY_STORE_NAME)) { db.createObjectStore(SEARCH_HISTORY_STORE_NAME, {keyPath: "id"}); const initSearchHistory = {id: 'searchHistory', records: []}; const transaction = event.target.transaction; const historyStore = transaction.objectStore(SEARCH_HISTORY_STORE_NAME); historyStore.add(initSearchHistory); } if (!db.objectStoreNames.contains(USER_SETTINGS_STORE_NAME)) { db.createObjectStore(USER_SETTINGS_STORE_NAME, {keyPath: "id"}); const transaction = event.target.transaction; const userSettingsStore = transaction.objectStore(USER_SETTINGS_STORE_NAME); const mainTreeBtnColorSettings = {id: 'mainTreeBtn', color: '#0FD126', opacity: 0.9}; userSettingsStore.add(mainTreeBtnColorSettings); const mainTreeBtnPosSettings = {id: 'mainTreeBtnPos', top: '20px', left: '20px'}; userSettingsStore.add(mainTreeBtnPosSettings); } }; request.onsuccess = event => { db = event.target.result; dbOperations.getSearchHistory() .then(records => { log('Got search history:', records); }) .catch(error => console.error(error)); dbOperations.getMainTreeBtnSettings('mainTreeBtn') .then(MainTreeBtnSettings => { log('Got MainTreeBtnSettings:', MainTreeBtnSettings); GlobalMainTreeBtnColorSettings = MainTreeBtnSettings; treeMainBtn.style.background = GlobalMainTreeBtnColorSettings.color; treeMainBtn.style.opacity = GlobalMainTreeBtnColorSettings.opacity; }) .catch(error => console.error(error)); dbOperations.getMainTreeBtnSettings('mainTreeBtnPos') .then(mainTreeBtnPos => { log('Got mainTreeBtnPosSettings:', mainTreeBtnPos); GlobalMainTreeBtnPositionSettings = mainTreeBtnPos; treeMainBtn.style.top = GlobalMainTreeBtnPositionSettings.top; treeMainBtn.style.left = GlobalMainTreeBtnPositionSettings.left; }) .catch(error => console.error(error)); resolve(); }; }); }, saveConversationsData: function (data) { if (data.url === null) { log("保存数据:No URL key specified."); return; } return new Promise((resolve, reject) => { if (!db) { console.error("保存数据:Database has not been initialized."); return; } if (!data.url) { reject("保存数据:No URL key specified."); return; } const transaction = db.transaction([CONVERSATIONS_STORE_NAME], "readwrite"); const objectStore = transaction.objectStore(CONVERSATIONS_STORE_NAME); const request = objectStore.put(data); request.onsuccess = () => resolve(); request.onerror = event => reject("Error saving data:", event.target.errorCode); }); }, getMainTreeBtnSettings: function (key) { return new Promise((resolve, reject) => { const transaction = db.transaction([USER_SETTINGS_STORE_NAME], 'readonly'); const store = transaction.objectStore(USER_SETTINGS_STORE_NAME); const request = store.get(key); request.onsuccess = function (event) { const settings = event.target.result; log(settings); resolve(settings); }; request.onerror = function (event) { console.error('读取设置失败', event.target.errorCode); reject(event.target.errorCode); }; }); }, updateMainTreeBtnSettings: function (newSettings) { return new Promise((resolve, reject) => { const transaction = db.transaction([USER_SETTINGS_STORE_NAME], 'readwrite'); const store = transaction.objectStore(USER_SETTINGS_STORE_NAME); const request = store.put(newSettings); request.onsuccess = function (event) { log('设置更新成功'); resolve(); }; request.onerror = function (event) { console.error('更新设置失败', event.target.errorCode); reject(event.target.errorCode); }; }); }, loadConversationsData: function (url) { if (!url || !urlOperations.isValidURL(url)) { return; } return new Promise((resolve, reject) => { if (!db) { console.error("加载数据:Database has not been initialized."); return; } if (!url) { reject("加载数据:No URL key specified."); return; } const transaction = db.transaction([CONVERSATIONS_STORE_NAME], "readwrite"); const objectStore = transaction.objectStore(CONVERSATIONS_STORE_NAME); const request = objectStore.get(url); request.onsuccess = event => { let result = event.target.result; log(" resultOfRequest:", result); if (!result) { let conversationData = { url: url, rootNode: new DialogueNode("Chat Starts Here", "chatGPT"), uuid2pathMap: new Map(), uuid2nodeMap: new Map(), path2nodeMap: new Map(), bookMarked: new Map(), timestamp: Date.now(), participants: { user: { name: "UserName", avatarURL: "UserAvatarURL", avatarHTML: "User", }, gpt: { type: "GPT-3", } } }; conversationData.uuid2nodeMap.set(conversationData.rootNode.uuid, conversationData.rootNode); conversationData.uuid2pathMap.set(conversationData.rootNode.uuid, []); conversationData.path2nodeMap.set('', conversationData.rootNode); log("在load中: data", conversationData); const addRequest = objectStore.add(conversationData); addRequest.onsuccess = () => { log("返回data:", conversationData); resolve(conversationData); } addRequest.onerror = event => reject("Error creating new data:", event.target.errorCode); } else { log("dataExisting!"); conversationData = result; if (!conversationData.bookMarked) { conversationData.bookMarked = new Map(); } if (!conversationData.participants) { conversationData.participants = { user: { name: "UserName", avatarURL: "UserAvatarURL", avatarHTML: "User", }, gpt: { type: "GPT-3", } } } root = d3.hierarchy(conversationData.rootNode); const widthPerNode = 30; const heightPerNode = 30; treeLayout = d3.tree().nodeSize([widthPerNode, heightPerNode]); treeLayout(root); settingsKit.refreshTree(); resolve(result); } }; request.onerror = event => reject("Error loading data:", event.target.errorCode); }); }, deleteConversationData: function (url) { return new Promise((resolve, reject) => { if (!url || !urlOperations.isValidURL(url)) { reject('Invalid URL'); return; } if (!db) { console.error('删除数据: Database has not been initialized.'); reject('Database not initialized'); return; } const transaction = db.transaction([CONVERSATIONS_STORE_NAME], 'readwrite'); const objectStore = transaction.objectStore(CONVERSATIONS_STORE_NAME); const deleteRequest = objectStore.delete(url); deleteRequest.onsuccess = () => { log(`Data for URL ${url} has been deleted.`); resolve(); }; deleteRequest.onerror = event => { console.error('Error deleting data:', event.target.errorCode); reject(event.target.errorCode); }; }); }, addSearchRecord: function (records) { return new Promise((resolve, reject) => { const transaction = db.transaction([SEARCH_HISTORY_STORE_NAME], 'readwrite'); const store = transaction.objectStore(SEARCH_HISTORY_STORE_NAME); const request = store.put({id: 'searchRecords', records: records}); request.onsuccess = () => { log('搜索记录已成功更新'); resolve(); }; request.onerror = () => { console.error('更新搜索记录时出错'); reject(new Error('更新搜索记录时出错')); }; }); }, getSearchHistory: function () { return new Promise((resolve, reject) => { const transaction = db.transaction([SEARCH_HISTORY_STORE_NAME], 'readonly'); const store = transaction.objectStore(SEARCH_HISTORY_STORE_NAME); const request = store.get('searchRecords'); request.onsuccess = event => { const records = event.target.result?.records || []; log('搜索历史记录:', records); searchHistoryRecord = records; resolve(records); }; request.onerror = event => { console.error('获取搜索历史记录失败'); reject(new Error('获取搜索历史记录失败')); }; }); } }; const DOMOperations = { getAllDivs: function () { return document.querySelectorAll('div[data-testid^="conversation-turn-"]'); }, clickButtonAtDivLevel: function (buttonIndex, divLevel = -1,) { let allChatDivs = DOMOperations.getAllDivs(); let conversationDiv = allChatDivs[divLevel]; if (conversationDiv) { const buttonInfoDiv = conversationDiv.querySelector('.text-xs.absolute.left-0'); let buttons = buttonInfoDiv.querySelectorAll("button"); log("In clickButtonAtDivLevel", "divLevel: ", divLevel, "buttons:", buttons); buttons[buttonIndex].click(); } else { log("TargetDiv Not found!"); } }, getButtonInfo: function () { log("In getButtonInfo!"); let hasRightButtonUnClicked = false; let hasLeftButtonUnClicked = false; let allChatDivs = DOMOperations.getAllDivs(); let childIndicesPath = []; let childrenCountPath = []; for (let i = 0; i < allChatDivs.length; i++) { let div = allChatDivs[i]; const buttonInfoDiv = div.querySelector('.text-xs.absolute.left-0'); if (buttonInfoDiv) { let span = buttonInfoDiv.querySelector("span"); if (span) { let spanText = span.innerText || span.textContent; let match = spanText.match(/(\d+) \/ (\d+)/); if (match) { let currentVersion = parseInt(match[1], 10); let totalVersions = parseInt(match[2], 10); childIndicesPath.push(currentVersion); childrenCountPath.push(totalVersions); } else { childIndicesPath.push(1); childrenCountPath.push(1); } } else { childIndicesPath.push(1); childrenCountPath.push(1); } } else { log("!didNot find the targetDiv of buttons!"); childIndicesPath.push(1); childrenCountPath.push(1); } } log("divlength:", allChatDivs.length, "childIndices:", childIndicesPath, "childrenCount", childrenCountPath); for (let i = 0; i < childrenCountPath.length; i++) { if (childIndicesPath[i] !== 1) hasLeftButtonUnClicked = true; if (childIndicesPath[i] !== childrenCountPath[i]) hasRightButtonUnClicked = true; } return { childIndicesPath: childIndicesPath, childrenCountPath: childrenCountPath, hasRightButtonUnClicked: hasRightButtonUnClicked, hasLeftButtonUnClicked: hasLeftButtonUnClicked }; }, getTextContent: function (div, i) { let isUser = null; let isGPT = null; if (i % 2) { isGPT = div.querySelector(".markdown.prose"); } else { isUser = div.querySelector('div.flex.flex-col.items-start.gap-3.overflow-x-auto.whitespace-pre-wrap.break-words'); } let userType = isUser ? "用户" : "chatGPT"; if (!userType) { userType = i % 2 ? "chatGPT" : "用户"; } let contentText; if (userType === "用户") if (isUser) contentText = isUser.innerText; else contentText = ''; else { if (isGPT) contentText = isGPT.innerHTML; else contentText = ''; } return { userType: userType, contentText: contentText } } }; function arrayToKey(arr) { return arr.join('|'); } function generateUUID() { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (c) { var r = Math.random() * 16 | 0, v = c === 'x' ? r : (r & 0x3 | 0x8); return v.toString(16); }); } function start() { ButtonOperations.showUserNotification(translate("chatTreeRunning")); dbOperations.initDatabase().then(() => { if (!db) { ButtonOperations.showUserNotification(translate("noDatabaseAndCreationFailed")); return; } log("Database initialized successfully."); log("database:", db); urlOperations.observeTargetChanges(); }).catch(error => { console.error("Error initializing database:", error); }); } function toggleSvgShow(isShowSvgButton = 0){ let mainSvg = document.getElementById("mainSvg") let mainSvgDiv = document.getElementById("mainSvgDiv") let thumbnail = document.getElementById("thumbnailSvg") let isMainSvgsDisplayed = mainSvgDiv.style.display; if (states.visualization.thumbnailSvg === 0) { states.visualization.thumbnailSvg = thumbnail.getAttribute("visibility"); states.visualization.contentDiv = contentDiv.style.display; } log("states.visualization.thumbnailSvg", states.visualization.thumbnailSvg); if (isMainSvgsDisplayed === 'block') { mainSvgDiv.style.display = "none"; settingsContainer.style.display = "none"; searchContainer.style.display = 'none'; mainSvg.setAttribute("visibility", "hidden"); if (states.visualization.thumbnailSvg === "visible") { thumbnail.setAttribute("visibility", "hidden"); } if (states.visualization.contentDiv === 'block') { contentDiv.style.display = 'none'; } commentForm.style.display = 'none'; document.documentElement.style.overflow = ''; } else if(isShowSvgButton){ mainSvgDiv.style.display = "block"; settingsContainer.style.display = "block"; searchContainer.style.display = 'flex'; mainSvg.setAttribute("visibility", "visible"); if (states.visualization.contentDiv === 'block') { contentDiv.style.display = 'block'; } if (states.visualization.thumbnailSvg === "visible") { thumbnail.setAttribute("visibility", "visible"); } states.visualization.thumbnailSvg = 0; states.visualization.contentDiv = 0; document.documentElement.style.overflow = 'hidden'; } } window.addEventListener('keydown', function(event) { if (event.key === 'Escape' || event.keyCode === 27) { log('Esc key was pressed'); toggleSvgShow(); } }); let treeMainBtn = document.createElement("button"); let isDragging = false; let isMouseOver = false; let offsetX, offsetY; let menu; let colorPicker, opacityPicker; const ButtonOperations = { createButton: function () { treeMainBtn.style.display = 'none'; treeMainBtn.className = 'main-button' treeMainBtn.id = "chatTreeBtn"; treeMainBtn.innerHTML = "🌳ChatTree🌳"; treeMainBtn.style.position = "fixed"; //treeMainBtn.style.right = '20px'; //treeMainBtn.style.top = '20px'; try{ treeMainBtn.style.left = GlobalMainTreeBtnPositionSettings.left ? GlobalMainTreeBtnPositionSettings.left : '20px'; treeMainBtn.style.top = GlobalMainTreeBtnPositionSettings.top ? GlobalMainTreeBtnPositionSettings.top : '20px'; } catch (e){ treeMainBtn.style.right = '30%'; treeMainBtn.style.top = '20px'; } treeMainBtn.style.zIndex = "9999"; treeMainBtn.style.resize = "both"; treeMainBtn.style.width = "150px"; treeMainBtn.style.height = "30px"; treeMainBtn.style.backgroundColor = GlobalMainTreeBtnColorSettings? GlobalMainTreeBtnColorSettings.color : "rgb(16,209,38)"; treeMainBtn.style.opacity = GlobalMainTreeBtnColorSettings? GlobalMainTreeBtnColorSettings.opacity : "0.9"; treeMainBtn.style.borderRadius = "12px"; document.body.appendChild(treeMainBtn); treeMainBtn.style.display = 'block'; treeMainBtn.addEventListener("mouseenter", ButtonOperations.showMenu); treeMainBtn.addEventListener("mouseleave", ButtonOperations.hideMenuIfNotOver); treeMainBtn.addEventListener("mousedown", ButtonOperations.onMouseDown); treeMainBtn.addEventListener("click", ButtonOperations.onClick); }, onMouseDown: function (e) { if (e.button !== 0) return; let rect = treeMainBtn.getBoundingClientRect(); offsetX = e.clientX - rect.left; offsetY = e.clientY - rect.top; isDragging = true; window.addEventListener("mousemove", ButtonOperations.onMouseMove); window.addEventListener("mouseup", ButtonOperations.onMouseUp); }, onMouseMove: function (e) { if (!isDragging) return; ButtonOperations.hideMenu(); let top = e.clientY - offsetY; let left = e.clientX - offsetX; let maxWidth = window.innerWidth; let maxHeight = window.innerHeight; let elementWidth = treeMainBtn.offsetWidth; let elementHeight = treeMainBtn.offsetHeight; if (left < 0) { left = 0; } else if (left > maxWidth - elementWidth) { left = maxWidth - elementWidth; } if (top < 0) { top = 0; } else if (top > maxHeight - elementHeight) { top = maxHeight - elementHeight; } treeMainBtn.style.left = left + "px"; treeMainBtn.style.top = top + "px"; treeMainBtn.style.right = "auto"; treeMainBtn.style.bottom = "auto"; }, onMouseUp: function () { isDragging = false; const newSettings = {id: 'mainTreeBtnPos', left: treeMainBtn.style.left, top: treeMainBtn.style.top}; dbOperations.updateMainTreeBtnSettings(newSettings).then(() => { }).catch(error => { console.error("Error saving Change:", error); }); window.removeEventListener("mousemove", ButtonOperations.onMouseMove); window.removeEventListener("mouseup", ButtonOperations.onMouseUp); }, onClick: function (e) { if (isDragging) { e.stopPropagation(); e.preventDefault(); ButtonOperations.hideMenu(); } }, showMenu: function () { if (isDragging) return; isMouseOver = true; if (menu) return; menu = document.createElement("div"); let updateCurrentConversationTreeText = translate("updateCurrentConversationTree"); let adjustBackgroundColorAndOpacityText = translate("adjustBackgroundColorAndOpacity"); let toggleConversationTreeText = translate("toggleConversationTree"); menu.innerHTML = ` `; menu.style.position = "fixed"; menu.style.zIndex = "10000"; menu.style.backgroundColor = "transparent"; menu.style.border = "none"; document.body.appendChild(menu); ButtonOperations.positionMenu(); const menuOptions = menu.querySelectorAll('.menu-option'); menuOptions.forEach((el, index) => { el.style.transition = 'all 400ms ease-out'; el.style.transform = `translateX(${treeMainBtn.getBoundingClientRect().width / 3}px)`; el.style.opacity = Math.max(0.2, parseFloat(treeMainBtn.style.opacity) - 0.4); setTimeout(() => { el.style.transform = 'translateX(0)'; el.style.opacity = treeMainBtn.style.opacity; }, index * 100); }) function rgbToHsl(r, g, b) { r /= 255, g /= 255, b /= 255; let max = Math.max(r, g, b), min = Math.min(r, g, b); let h, s, l = (max + min) / 2; if (max === min) { h = s = 0; } else { let d = max - min; s = l > 0.5 ? d / (2 - max - min) : d / (max + min); switch (max) { case r: h = (g - b) / d + (g < b ? 6 : 0); break; case g: h = (b - r) / d + 2; break; case b: h = (r - g) / d + 4; break; } h /= 6; } return [h, s, l]; } function hslToRgb(h, s, l) { let r, g, b; if (s === 0) { r = g = b = l; } else { function hue2rgb(p, q, t) { if (t < 0) t += 1; if (t > 1) t -= 1; if (t < 1 / 6) return p + (q - p) * 6 * t; if (t < 1 / 2) return q; if (t < 2 / 3) return p + (q - p) * (2 / 3 - t) * 6; return p; } let q = l < 0.5 ? l * (1 + s) : l + s - l * s; let p = 2 * l - q; r = hue2rgb(p, q, h + 1 / 3); g = hue2rgb(p, q, h); b = hue2rgb(p, q, h - 1 / 3); } return [r * 255, g * 255, b * 255]; } menuOptions.forEach(option => { option.addEventListener('mouseover', () => { const bgColor = window.getComputedStyle(treeMainBtn).backgroundColor; const rgb = bgColor.match(/[\d.]+/g).map(Number); let [h, s, l] = rgbToHsl(...rgb); l *= 0.8 const [r, g, b] = hslToRgb(h, s, l); option.style.backgroundColor = `rgb(${Math.round(r)}, ${Math.round(g)}, ${Math.round(b)})`; }); option.addEventListener('mouseout', () => { option.style.backgroundColor = treeMainBtn.style.backgroundColor; }); }); menu.addEventListener("click", ButtonOperations.onMenuClick); menu.addEventListener("mouseenter", () => isMouseOver = true); menu.addEventListener("mouseleave", ButtonOperations.hideMenuIfNotOver); colorPicker = document.getElementById('colorPicker'); opacityPicker = document.getElementById('opacityPicker'); colorPicker.addEventListener('input', ButtonOperations.onColorChange); colorPicker.addEventListener('change', ButtonOperations.onColorChangeDone); opacityPicker.addEventListener('input', ButtonOperations.onOpacityChange); opacityPicker.addEventListener('change', ButtonOperations.onOpacityChangeDone); document.querySelectorAll('.menu-option').forEach(el => { el.style.backgroundColor = treeMainBtn.style.backgroundColor; el.style.opacity = treeMainBtn.style.opacity; }); }, hideMenuIfNotOver: function () { isMouseOver = false; setTimeout(() => { if (!isMouseOver) ButtonOperations.hideMenu(); }, 100); }, hideMenu: function () { if (menu) { document.body.removeChild(menu); menu = null; } }, onMenuClick: function (e) { if (e.target.id === 'adjustOption') { colorPicker.style.display = 'inline-block'; opacityPicker.style.display = 'inline-block'; } if (e.target.id === 'opt_updateTree') { let curURL = window.location.href; log("curURL:", curURL, "states:", states); if (curURL !== states.url.url) { if (urlOperations.isValidURL(curURL)) { if (confirm(translate("confirmCurrentURL").replace('{item}', curURL))) { urlOperations.handleURLChange(curURL); ButtonOperations.showUserNotification(translate("startUpdatingConversationTree")); } else { return; } } else { alert("Please Refresh The Page First!🔄️") return; } } log("按钮点击而开始更新树!states:", states); if (states.url.isValidURL === true && states.url.url !== '' && !states.treeUpdate.isDOMOperating) { log("由于按钮点击而开始更新树!"); let allDivs = DOMOperations.getAllDivs(); if (allDivs.length === 0) { log("没有检测到Div!请刷新页面获取对话信息!"); return; } setTimeout(() => treeOperation.initializeChatTree(), 1000); } else { log("按钮点击而开始更新树!但是条件不允许!states:", states); } } if (e.target.id === 'showSvg') { toggleSvgShow(1); } if (e.target.innerText != '') ButtonOperations.showUserNotification(translate("selectedItem").replace('{item}', e.target.innerText)); }, currentMessages: 0, showUserNotification: function (text, alertOrNote = "note", duration = 3000) { const message = document.createElement("div"); const innerHtml = (alertOrNote === "note") ? `Click to take the survey(Google Forms)