diff --git a/lang/fr/lang.php b/lang/fr/lang.php
new file mode 100644
index 0000000..94123d6
--- /dev/null
+++ b/lang/fr/lang.php
@@ -0,0 +1,16 @@
+🔄 Vous devez reconstruire le stockage vectoriel après modification de ce paramètre.';
+$lang['storage'] = 'Quel stockage vectoriel 💾 utiliser. Configurez les identifiants nécessaires ci-dessous.
🔄 Vous devez reconstruire le stockage vectoriel après modification de ce paramètre.';
+$lang['customprompt'] = 'Une invite personnalisée ajoutée à celle utilisée par cette extension lors des requêtes au modèle IA. Pour plus de cohérence, elle doit être en anglais.';
+
+$lang['openai_apikey'] = '🧠 Clé API OpenAI';
+$lang['openai_org'] = '🧠 ID d\'organisation OpenAI (le cas échéant)';
+$lang['gemini_apikey'] = '🧠 Clé API Google Gemini';
+$lang['anthropic_apikey'] = '🧠 Clé API Anthropic';
+$lang['mistral_apikey'] = '🧠 Clé API Mistral';
+$lang['voyageai_apikey'] = '🧠 Clé API Voyage AI';
+$lang['reka_apikey'] = '🧠 Clé API Reka';
+$lang['groq_apikey'] = '🧠 Clé API Groq';
+$lang['ollama_baseurl'] = '🧠 URL de base Ollama';
+
+$lang['pinecone_apikey'] = '💾 Clé API Pinecone';
+$lang['pinecone_baseurl'] = '💾 URL de base Pinecone';
+
+$lang['chroma_baseurl'] = '💾 URL de base Chroma';
+$lang['chroma_apikey'] = '💾 Clé API Chroma. Laisser vide si aucune authentification n\'est requise';
+$lang['chroma_tenant'] = '💾 Nom du tenant Chroma';
+$lang['chroma_database'] = '💾 Nom de la base de données Chroma';
+$lang['chroma_collection'] = '💾 Collection Chroma. Sera créée.';
+
+$lang['qdrant_baseurl'] = '💾 URL de base Qdrant';
+$lang['qdrant_apikey'] = '💾 Clé API Qdrant. Laisser vide si aucune authentification n\'est requise';
+$lang['qdrant_collection'] = '💾 Collection Qdrant. Sera créée.';
+
+$lang['chunkSize'] = 'Nombre maximal de jetons par bloc.
🔄 Vous devez reconstruire le stockage vectoriel après modification de ce paramètre.';
+$lang['similarityThreshold'] = 'Seuil minimal de similarité lors de la sélection des sources pour une question. 0-100.';
+$lang['contextChunks'] = 'Nombre maximal de blocs à envoyer au modèle IA pour le contexte.';
+$lang['chatHistory'] = 'Nombre de messages précédents à prendre en compte pour le contexte de la conversation.';
+$lang['rephraseHistory'] = 'Nombre de messages précédents à prendre en compte lors de la reformulation d\'une question. Mettre 0 pour désactiver la reformulation.';
+
+$lang['logging'] = 'Journaliser toutes les questions et réponses. Utilisez le visionneur de logs pour y accéder.';
+$lang['restrict'] = 'Restreindre l\'accès à ces utilisateurs et groupes (séparés par des virgules). Laisser vide pour autoriser tous les utilisateurs.';
+$lang['skipRegex'] = 'Ignorer l\'indexation des pages correspondant à cette expression régulière (sans délimiteurs).
🔄 Vous devez reconstruire le stockage vectoriel après modification de ce paramètre.';
+$lang['matchRegex'] = 'Indexer uniquement les pages correspondant à cette expression régulière (sans délimiteurs).
🔄 Vous devez reconstruire le stockage vectoriel après modification de ce paramètre.';
+$lang['ignoreRegex'] = 'Ignorer les parties du contenu correspondant à cette expression régulière (sans délimiteurs).
🔄 Vous devez reconstruire le stockage vectoriel après modification de ce paramètre.';
+$lang['preferUIlanguage'] = 'Comment gérer les wikis multilingues ? (nécessite le plugin de traduction)';
+
+$lang['preferUIlanguage_o_0'] = 'Deviner la langue, utiliser toutes les sources';
+$lang['preferUIlanguage_o_1'] = 'Préférer la langue de l\'interface, utiliser toutes les sources';
+$lang['preferUIlanguage_o_2'] = 'Préférer la langue de l\'interface, sources uniquement dans la même langue';
diff --git a/script/AIChatChat.js b/script/AIChatChat.js
index cfcf0b2..1992acd 100644
--- a/script/AIChatChat.js
+++ b/script/AIChatChat.js
@@ -175,6 +175,17 @@ class AIChatChat extends HTMLElement {
border-top: 0.5em solid var(--color-ai);
border-bottom: 0.5em solid transparent;
}
+ details.think {
+ font-size: 0.8em;
+ margin: 0.5em 0;
+ }
+ details.think summary {
+ cursor: pointer;
+ }
+ details.think .think-content {
+ max-height: 10em;
+ overflow-y: auto;
+ }
`;
return style;
}
@@ -281,8 +292,11 @@ class AIChatChat extends HTMLElement {
*/
displayMessage(message, sources = null) {
const div = document.createElement('div');
- if(sources !== null) {
+ const isAI = sources !== null || /(?:<|<)\s*think(?:>|>)/i.test(message);
+ if (isAI) {
div.classList.add('ai');
+ message = message.replace(/(?:<|<)\s*think(?:>|>)([\s\S]*?)(?:<|<)\s*\/\s*think(?:>|>)/gi,
+ (m, c) => `thinking...
${c}
`);
div.innerHTML = message; // we get HTML for AI messages
} else {
div.classList.add('user');
@@ -304,6 +318,24 @@ class AIChatChat extends HTMLElement {
}
this.#output.appendChild(div);
+ div.querySelectorAll('details.think').forEach(det => {
+ const box = det.querySelector('.think-content');
+ const scroll = () => {
+ if(box.scrollTop < box.scrollHeight - box.clientHeight) {
+ box.scrollTop += 1;
+ box._timer = requestAnimationFrame(scroll);
+ }
+ };
+ det.addEventListener('toggle', () => {
+ if(det.open) {
+ cancelAnimationFrame(box._timer);
+ box.scrollTop = 0;
+ box._timer = requestAnimationFrame(scroll);
+ } else if(box._timer) {
+ cancelAnimationFrame(box._timer);
+ }
+ });
+ });
return div;
}