Merge branch 'next' into add-pt-locale
This commit is contained in:
		
						commit
						b3d9f3ca92
					
				| @ -19,10 +19,10 @@ Thank you for your interest in contributing to Page Assist! We welcome contribut | ||||
| 
 | ||||
| 3. **Install dependencies** | ||||
| 
 | ||||
|    Page Assist uses [Yarn](https://yarnpkg.com/) for dependency management. Install the required dependencies by running the following command in the project root directory: | ||||
|    Page Assist uses [Bun](https://bun.sh/) for dependency management. Install the required dependencies by running the following command in the project root directory: | ||||
| 
 | ||||
|    ``` | ||||
|    yarn install | ||||
|    bun install | ||||
|    ``` | ||||
| 
 | ||||
| 4. **Start the development server** | ||||
| @ -30,10 +30,16 @@ Thank you for your interest in contributing to Page Assist! We welcome contribut | ||||
|    To run the extension in development mode, use the following command: | ||||
| 
 | ||||
|    ``` | ||||
|    yarn dev | ||||
|    bun dev | ||||
|    ``` | ||||
| 
 | ||||
|    This will open a browser window with the extension loaded. | ||||
|    This will open a  chrome browser window with the extension loaded. | ||||
| 
 | ||||
|    for firefox: | ||||
| 
 | ||||
|    ``` | ||||
|    bun dev:firefox | ||||
|    ``` | ||||
| 
 | ||||
| 5. **Install Ollama locally** | ||||
| 
 | ||||
|  | ||||
							
								
								
									
										11
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										11
									
								
								README.md
									
									
									
									
									
								
							| @ -30,13 +30,6 @@ Checkout the Demo (v1.0.0): | ||||
| 
 | ||||
| want more features? Create an issue and let me know. | ||||
| 
 | ||||
| <!-- ## Installation | ||||
| 
 | ||||
| ### Chrome Web Store | ||||
| 
 | ||||
| You can install the extension from the [Chrome Web Store](https://chromewebstore.google.com/detail/page-assist-a-web-ui-for/jfgfiigpkhlkbnfnbobbkinehhfdhndo) | ||||
| 
 | ||||
| Note: You can install the extension on any Chromium-based browser. It is not limited to Chrome. --> | ||||
| 
 | ||||
| ### Manual Installation | ||||
| 
 | ||||
| @ -125,6 +118,8 @@ This will start a development server and watch for changes in the source files. | ||||
| | Opera    | ❌      | ❌                | ✅     | | ||||
| | Arc      | ❌      | ❌                | ✅     | | ||||
| 
 | ||||
| 
 | ||||
| 
 | ||||
| ## Local AI Provider | ||||
| 
 | ||||
| - [Ollama](https://github.com/ollama/ollama) (Currently the only supported provider. More providers will be added in the future.) | ||||
| @ -132,8 +127,8 @@ This will start a development server and watch for changes in the source files. | ||||
| ## Roadmap | ||||
| 
 | ||||
| - [X] Firefox Support | ||||
| - [ ] Code Completion support for Web based IDEs (like Colab, Jupyter, etc.) | ||||
| - [ ] More Local AI Providers | ||||
| - [ ] More Features | ||||
| - [ ] More Customization Options | ||||
| - [ ] Better UI/UX | ||||
| 
 | ||||
|  | ||||
| @ -8,7 +8,7 @@ | ||||
|     "dev": "cross-env TARGET=chrome wxt", | ||||
|     "dev:firefox": "cross-env TARGET=firefox wxt -b firefox", | ||||
|     "build": "cross-env TARGET=chrome wxt build", | ||||
|     "build:firefox": "cross-env TARGET=chrome cross-env TARGET=firefox wxt build -b firefox", | ||||
|     "build:firefox": "cross-env TARGET=firefox wxt build -b firefox", | ||||
|     "zip": "cross-env TARGET=chrome wxt zip", | ||||
|     "zip:firefox": "cross-env TARGET=firefox wxt zip -b firefox", | ||||
|     "compile": "tsc --noEmit", | ||||
|  | ||||
							
								
								
									
										88
									
								
								src/assets/locale/fr/common.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/assets/locale/fr/common.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | ||||
| { | ||||
|     "pageAssist": "Page Assist", | ||||
|     "selectAModel": "Sélectionnez un modèle", | ||||
|     "save": "Sauvegarder", | ||||
|     "saved": "Enregistrée", | ||||
|     "cancel": "Annuler", | ||||
|     "retry": "Recommencez", | ||||
|     "share": { | ||||
|         "tooltip": { | ||||
|             "share": "Partager" | ||||
|         }, | ||||
|         "modal": { | ||||
|             "title": "Partagez le lien vers le chat" | ||||
|         }, | ||||
|         "form": { | ||||
|             "defaultValue": { | ||||
|                 "name": "Anonyme", | ||||
|                 "title": "Chat sans titre" | ||||
|             }, | ||||
|             "title": { | ||||
|                 "label": "Titre de chat", | ||||
|                 "placeholder": "Entrez le titre du chat", | ||||
|                 "required": "Le titre de chat est requis" | ||||
|             }, | ||||
|             "name": { | ||||
|                 "label": "Votre nom", | ||||
|                 "placeholder": "Entrez votre nome", | ||||
|                 "required": "Votre nom est requis" | ||||
|             }, | ||||
|             "btn": { | ||||
|                 "save": "Générer un lien", | ||||
|                 "saving": "Génération de lien..." | ||||
|             } | ||||
|         }, | ||||
|         "notification": { | ||||
|             "successGenerate": "Lien copié dans le presse-papiers", | ||||
|             "failGenerate": "Échec de la génération de lien" | ||||
|         } | ||||
|     }, | ||||
|     "copyToClipboard": "Copier dans le presse-papier", | ||||
|     "webSearch": "Recherche sur le Web", | ||||
|     "regenerate": "Régénérer", | ||||
|     "edit": "Modifier", | ||||
|     "saveAndSubmit": "Enregistrer et soumettre", | ||||
|     "editMessage": { | ||||
|         "placeholder": "Tapez un message..." | ||||
|     }, | ||||
|     "submit": "Soumettre", | ||||
|     "noData": "Pas de données", | ||||
|     "noHistory": "Pas d'historique de chat", | ||||
|     "chatWithCurrentPage": "Discuter avec la page actuelle", | ||||
|     "beta": "Bêta", | ||||
|     "tts": "Synthèse vocale", | ||||
|     "currentChatModelSettings":"Paramètres actuels du modèle de chat", | ||||
|     "modelSettings": { | ||||
|         "label": "Paramètres du modèle", | ||||
|         "description": "Définissez les options de modèle globale pour tous les chats", | ||||
|         "form": { | ||||
|             "keepAlive": { | ||||
|                 "label": "Maintenir en mémoire", | ||||
|                 "help": "contrôle combien de temps le modèle restera chargé en mémoire après la demande (par défaut: 5m)", | ||||
|                 "placeholder": "Entrer la durée du maintien en mémoire (p. ex., 5 m, 10 m, 1 h)" | ||||
|             }, | ||||
|             "temperature": { | ||||
|                 "label": "Température", | ||||
|                 "placeholder": "Entrez la valeur de la température (par exemple 0,7, 1,0)" | ||||
|             }, | ||||
|             "numCtx": { | ||||
|                 "label": "Nombre de contextes", | ||||
|                 "placeholder": "Entrez la valeur du nombre de contextes (par défaut: 2048)" | ||||
|             }, | ||||
|             "seed": { | ||||
|                 "label": "Graine", | ||||
|                 "placeholder": "Entrez la valeur des semences (par exemple 1234)", | ||||
|                 "help": "Reproductibilité de la sortie du modèle" | ||||
|             }, | ||||
|             "topK": { | ||||
|                 "label": "Top K", | ||||
|                 "placeholder": "Entrez la valeur Top K (par exemple 40, 100)" | ||||
|             }, | ||||
|             "topP": { | ||||
|                 "label": "Top P", | ||||
|                 "placeholder": "Entrez la valeur Top P (par exemple 0,9, 0,95)" | ||||
|             } | ||||
|         }, | ||||
|         "advanced": "Plus de paramètres du modèle" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										42
									
								
								src/assets/locale/fr/knowledge.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/assets/locale/fr/knowledge.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| { | ||||
|     "addBtn": "Ajouter de nouvelles connaissances", | ||||
|     "columns": { | ||||
|         "title": "Titre", | ||||
|         "status": "Statut", | ||||
|         "embeddings": "Modèle d'embedding", | ||||
|         "createdAt": "Créé à", | ||||
|         "action": "actions" | ||||
|     }, | ||||
|     "expandedColumns": { | ||||
|         "name": "Nom" | ||||
|     }, | ||||
|     "tooltip": { | ||||
|         "delete": "Supprimer" | ||||
|     }, | ||||
|     "confirm": { | ||||
|         "delete": "Êtes-vous sûr de vouloir supprimer ces connaissances ?" | ||||
|     }, | ||||
|     "deleteSuccess": "Connaissances supprimées avec succès", | ||||
|     "status": { | ||||
|         "pending": "En attente", | ||||
|         "finished": "Terminé", | ||||
|         "processing": "Traitement" | ||||
|     }, | ||||
|     "addKnowledge": "Ajouter des connaissances", | ||||
|     "form": { | ||||
|         "title": { | ||||
|             "label": "Titre de la connaissance", | ||||
|             "placeholder": "Entrez le titre de la connaissances", | ||||
|             "required": "Le titre de la connaissance est requis" | ||||
|         }, | ||||
|         "uploadFile": { | ||||
|             "label": "Téléverser un fichier", | ||||
|             "uploadText": "Faites glisser et déposez un fichier ici ou cliquez pour téléverser", | ||||
|             "uploadHint": "Types de fichiers pris en charge: .pdf, .csv, .txt, .md, .docx", | ||||
|             "required": "Le fichier est requis" | ||||
|         }, | ||||
|         "submit": "Soumettre", | ||||
|         "success": "Les connaissances ont ajouté avec succès" | ||||
|     }, | ||||
|     "noEmbeddingModel": "Veuillez d'abord ajouter un modèle d'embedding depuis la page des paramètres de Ollama" | ||||
| } | ||||
							
								
								
									
										12
									
								
								src/assets/locale/fr/option.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/assets/locale/fr/option.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| { | ||||
|     "newChat": "Nouveau chat", | ||||
|     "selectAPrompt": "Sélectionnez un prompt", | ||||
|     "githubRepository": "Référentiel GitHub", | ||||
|     "settings": "Paramètres", | ||||
|     "sidebarTitle": "Historique de chat", | ||||
|     "error": "Erreur", | ||||
|     "somethingWentWrong": "Quelque chose s'est mal passé", | ||||
|     "validationSelectModel": "Veuillez sélectionner un modèle pour continuer", | ||||
|     "deleteHistoryConfirmation": "Êtes-vous sûr de vouloir supprimer cette historique ?", | ||||
|     "editHistoryTitle": "Entrez un nouveau titre" | ||||
| } | ||||
							
								
								
									
										29
									
								
								src/assets/locale/fr/playground.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/assets/locale/fr/playground.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| { | ||||
|     "ollamaState": { | ||||
|         "searching": "Searching for Your Ollama 🦙", | ||||
|         "running": "Ollama is running 🦙", | ||||
|         "notRunning": "Unable to connect to Ollama 🦙", | ||||
|         "connectionError": "It seems like you are having a connection error. Please refer to this <anchor>documentation</anchor> for troubleshooting." | ||||
|     }, | ||||
|     "formError": { | ||||
|         "noModel": "Please select a model", | ||||
|         "noEmbeddingModel": "Please set an embedding model on the Settings > Ollama page" | ||||
|     }, | ||||
|     "form": { | ||||
|         "textarea": { | ||||
|             "placeholder": "Type a message..." | ||||
|         }, | ||||
|         "webSearch": { | ||||
|             "on": "On", | ||||
|             "off": "Off" | ||||
|         } | ||||
|     }, | ||||
|     "tooltip": { | ||||
|         "searchInternet": "Rechercher Internet", | ||||
|         "speechToText": "Parole en texte", | ||||
|         "uploadImage": "Téléverser une image", | ||||
|         "stopStreaming": "Arrêtez la diffusion", | ||||
|         "knowledge": "Connaissance" | ||||
|     }, | ||||
|     "sendWhenEnter": "Envoyer en appuyant sur Entrée" | ||||
| } | ||||
							
								
								
									
										286
									
								
								src/assets/locale/fr/settings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								src/assets/locale/fr/settings.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,286 @@ | ||||
| { | ||||
|     "generalSettings": { | ||||
|         "title": "Réglages généraux", | ||||
|         "settings": { | ||||
|             "heading": "Paramètres d'interface utilisateur Web", | ||||
|             "speechRecognitionLang": { | ||||
|                 "label": "Langue de reconnaissance vocale", | ||||
|                 "placeholder": "Sélectionnez une langue" | ||||
|             }, | ||||
|             "language": { | ||||
|                 "label": "Langue", | ||||
|                 "placeholder": "Sélectionnez une langue" | ||||
|             }, | ||||
|             "darkMode": { | ||||
|                 "label": "Change le thème", | ||||
|                 "options": { | ||||
|                     "light": "Clair", | ||||
|                     "dark": "Sombre" | ||||
|                 } | ||||
|             }, | ||||
|             "copilotResumeLastChat": { | ||||
|                 "label": "Reprendre la dernière conversation lors de l'ouverture du sidepanel (Copilot)" | ||||
|             }, | ||||
|             "hideCurrentChatModelSettings": { | ||||
|                 "label": "Masquer les paramètres actuels du modèle de chat" | ||||
|             } | ||||
|         }, | ||||
|         "webSearch": { | ||||
|             "heading": "Gérer la recherche Web", | ||||
|             "searchMode": { | ||||
|                 "label": "Effectuer une simple recherche sur Internet" | ||||
|             }, | ||||
|             "provider": { | ||||
|                 "label": "Moteur de recherche", | ||||
|                 "placeholder": "Sélectionnez un moteur de recherche" | ||||
|             }, | ||||
|             "totalSearchResults": { | ||||
|                 "label": "Résultats de la recherche totaux", | ||||
|                 "placeholder": "Entrez les résultats de la recherche totaux" | ||||
|             } | ||||
|         }, | ||||
|         "system": { | ||||
|             "heading": "Les paramètres du système", | ||||
|             "deleteChatHistory": { | ||||
|                 "label": "Supprimer l'historique du chat", | ||||
|                 "button": "Supprimer", | ||||
|                 "confirm": "Êtes-vous sûr de vouloir supprimer l'historique de votre chat? Cette action ne peut pas être annulée." | ||||
|             }, | ||||
|             "export": { | ||||
|                 "label": "Exporter l'historique du chat, la base de connaissances et les invites", | ||||
|                 "button": "Exporter des données", | ||||
|                 "success": "Succès de l'exportation" | ||||
|             }, | ||||
|             "import": { | ||||
|                 "label": "Importer l'historique du chat, la base de connaissances et les invites", | ||||
|                 "button": "Importer des données", | ||||
|                 "success": "Succès d'importation", | ||||
|                 "error": "Erreur d'importation" | ||||
|             } | ||||
|         }, | ||||
|         "tts": { | ||||
|             "heading": "Paramètres de synthèse vocale", | ||||
|             "ttsEnabled": { | ||||
|                 "label": "Activer la synthèse vocale" | ||||
|             }, | ||||
|             "ttsProvider": { | ||||
|                 "label": "Fournisseur de synthèse vocale", | ||||
|                 "placeholder": "Sélectionnez un fournisseur" | ||||
|             }, | ||||
|             "ttsVoice": { | ||||
|                 "label": "Voix de synthèse vocale", | ||||
|                 "placeholder": "Sélectionnez une voix" | ||||
|             }, | ||||
|             "ssmlEnabled": { | ||||
|                 "label": "Activer SSML (langage de balisage de synthèse vocale)" | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "manageModels": { | ||||
|         "title": "Gérer les modèles", | ||||
|         "addBtn": "Ajouter un nouveau modèle", | ||||
|         "columns": { | ||||
|             "name": "Nom", | ||||
|             "digest": "Digérer", | ||||
|             "modifiedAt": "Modifié à", | ||||
|             "size": "Taille", | ||||
|             "actions": "Actions" | ||||
|         }, | ||||
|         "expandedColumns": { | ||||
|             "parentModel": "Modèle parent", | ||||
|             "format": "Format", | ||||
|             "family": "Famille", | ||||
|             "parameterSize": "Taille du paramètre", | ||||
|             "quantizationLevel": "Niveau de quantification" | ||||
|         }, | ||||
|         "tooltip": { | ||||
|             "delete": "Supprimer le modèle", | ||||
|             "repull": "Modèle de ré-échoue" | ||||
|         }, | ||||
|         "confirm": { | ||||
|             "delete": "Êtes-vous sûr de vouloir supprimer ce modèle?", | ||||
|             "repull": "Êtes-vous sûr de vouloir rétracter ce modèle?" | ||||
|         }, | ||||
|         "modal": { | ||||
|             "title": "Ajouter un nouveau modèle", | ||||
|             "placeholder": "Entrez le nom du modèle", | ||||
|             "pull": "Modèle de traction" | ||||
|         }, | ||||
|         "notification": { | ||||
|             "pullModel": "Modèle de traction", | ||||
|             "pullModelDescription": "Tirling {{ModelName}} modèle. Pour plus de détails, vérifiez l'icône d'extension.", | ||||
|             "success": "Succès", | ||||
|             "error": "Erreur", | ||||
|             "successDescription": "A réussi à tirer le modèle", | ||||
|             "successDeleteDescription": "Supprimé avec succès le modèle", | ||||
|             "someError": "Quelque chose s'est mal passé.Veuillez réessayer plus tard" | ||||
|         } | ||||
|     }, | ||||
|     "managePrompts": { | ||||
|         "title": "Gérer les prompts", | ||||
|         "addBtn": "Ajouter un nouveau prompt", | ||||
|         "option1": "Normale", | ||||
|         "option2": "RAG", | ||||
|         "questionPrompt": "Prompt de question", | ||||
|         "columns": { | ||||
|             "title": "Titre", | ||||
|             "prompt": "Prompt", | ||||
|             "type": "Type de prompt", | ||||
|             "actions": "Actions" | ||||
|         }, | ||||
|         "systemPrompt": "Prompt système", | ||||
|         "quickPrompt": "Prompt rapide", | ||||
|         "tooltip": { | ||||
|             "delete": "Supprimer le prompt", | ||||
|             "edit": "Modifier le prompt" | ||||
|         }, | ||||
|         "confirm": { | ||||
|             "delete": "Êtes-vous sûr de vouloir supprimer cette invite ? Cette action ne peut pas être annulée." | ||||
|         }, | ||||
|         "modal": { | ||||
|             "addTitle": "Ajouter un nouveau prompt", | ||||
|             "editTitle": "Modifier le prompt" | ||||
|         }, | ||||
|         "form": { | ||||
|             "title": { | ||||
|                 "label": "Titre", | ||||
|                 "placeholder": "Mon super prompt", | ||||
|                 "required": "Veuillez saisir un titre" | ||||
|             }, | ||||
|             "prompt": { | ||||
|                 "label": "Prompt", | ||||
|                 "placeholder": "Entrer Prompt", | ||||
|                 "required": "Veuillez entrer un prompt", | ||||
|                 "help": "Vous pouvez utiliser {key} comme variable dans votre prompt." | ||||
|             }, | ||||
|             "isSystem": { | ||||
|                 "label": "Est un prompt système" | ||||
|             }, | ||||
|             "btnSave": { | ||||
|                 "saving": "Ajout de Prompt...", | ||||
|                 "save": "Ajouter un prompt" | ||||
|             }, | ||||
|             "btnEdit": { | ||||
|                 "saving": "Mise à jour du Prompt...", | ||||
|                 "save": "Modifier le prompt" | ||||
|             } | ||||
|         }, | ||||
|         "notification": { | ||||
|             "addSuccess": "Prompt ajouté", | ||||
|             "addSuccessDesc": "Le prompt a été ajoutée avec succès", | ||||
|             "error": "Erreur", | ||||
|             "someError": "Quelque chose s'est mal passé. Veuillez réessayer plus tard", | ||||
|             "updatedSuccess": "Prompt mise à jour", | ||||
|             "updatedSuccessDesc": "Le prompt a été mis à jour avec succès", | ||||
|             "deletedSuccess": "Prompt supprimé", | ||||
|             "deletedSuccessDesc": "Le prompt a été supprimé avec succès" | ||||
|         } | ||||
|     }, | ||||
|     "manageShare": { | ||||
|         "title": "Gérer le partage", | ||||
|         "heading": "Configurer l'URL de partage de la page", | ||||
|         "form": { | ||||
|             "url": { | ||||
|                 "label": "URL de partage de page", | ||||
|                 "placeholder": "Entrez l'URL de partage de la page", | ||||
|                 "required": "Veuillez saisir URL de partage de votre page!", | ||||
|                 "help": "Pour des raisons de confidentialité, vous pouvez auto-héberger le partage de la page et fournir l'URL ici.<anchor>En savoir plus</anchor>." | ||||
|             } | ||||
|         }, | ||||
|         "webshare": { | ||||
|             "heading": "Partage Web", | ||||
|             "columns": { | ||||
|                 "title": "Titre", | ||||
|                 "url": "URL", | ||||
|                 "actions": "Actions" | ||||
|             }, | ||||
|             "tooltip": { | ||||
|                 "delete": "Supprimer le partage" | ||||
|             }, | ||||
|             "confirm": { | ||||
|                 "delete": "Êtes-vous sûr de vouloir supprimer ce partage ? Cette action ne peut pas être annulée." | ||||
|             }, | ||||
|             "label": "Gérer le partage de pages", | ||||
|             "description": "Activer ou désactiver la fonction de partage de page" | ||||
|         }, | ||||
|         "notification": { | ||||
|             "pageShareSuccess": "URL de partage de page mise à jour avec succès", | ||||
|             "someError": "Quelque chose a mal tourné. Veuillez réessayer plus tard", | ||||
|             "webShareDeleteSuccess": "Partage Web supprimé avec succès" | ||||
|         } | ||||
|     }, | ||||
|     "ollamaSettings": { | ||||
|         "title": "Réglages de Ollama", | ||||
|         "heading": "Configurer Ollama", | ||||
|         "settings": { | ||||
|             "ollamaUrl": { | ||||
|                 "label": "Url de Ollama", | ||||
|                 "placeholder": "Entrer l'url de Ollama" | ||||
|             }, | ||||
|             "ragSettings": { | ||||
|                 "label": "Paramètres de RAG", | ||||
|                 "model": { | ||||
|                     "label": "Modèle d'embedding", | ||||
|                     "required": "Veuillez sélectionner un modèle", | ||||
|                     "help": "Fortement recommandé d'utiliser des modèles d'embedding comme «momic-embed-text».", | ||||
|                     "placeholder": "Sélectionnez un modèle" | ||||
|                 }, | ||||
|                 "chunkSize": { | ||||
|                     "label": "Taille", | ||||
|                     "placeholder": "Entrez la taille du morceau", | ||||
|                     "required": "Veuillez saisir une taille" | ||||
|                 }, | ||||
|                 "chunkOverlap": { | ||||
|                     "label": "Chevauchement", | ||||
|                     "placeholder": "Entrez le chevauchement des morceaux", | ||||
|                     "required": "Veuillez saisir un chevauchement" | ||||
|                 } | ||||
|             }, | ||||
|             "prompt": { | ||||
|                 "label": "Configure RAG Prompt", | ||||
|                 "option1": "Normal", | ||||
|                 "option2": "Web", | ||||
|                 "alert": "La configuration du prompt système ici est déconseillée. Veuillez utiliser la section Gérer les prompts pour ajouter...", | ||||
|                 "systemPrompt": "Prompt système", | ||||
|                 "systemPromptPlaceholder": "Entrez le prompt système", | ||||
|                 "webSearchPrompt": "Prompt de recherche Web", | ||||
|                 "webSearchPromptHelp": "Ne supprimez pas `{search_results}` du prompt.", | ||||
|                 "webSearchPromptError": "Veuillez saisir un prompt de recherche Web", | ||||
|                 "webSearchPromptPlaceholder": "Entrez le prompt de recherche Web", | ||||
|                 "webSearchFollowUpPrompt": "Prompt de suivi de recherche Web", | ||||
|                 "webSearchFollowUpPromptHelp": "Ne supprimez pas `{chat_history}` et `{question}` du prompt.", | ||||
|                 "webSearchFollowUpPromptError": "Veuillez saisir votre prompt de suivi de recherche Web!", | ||||
|                 "webSearchFollowUpPromptPlaceholder": "Votre prompt de suivi de recherche Web" | ||||
|             }, | ||||
|             "advanced": { | ||||
|                 "label": "Configuration avancée de l'URL de Ollama", | ||||
|                 "urlRewriteEnabled": { | ||||
|                     "label": "Activer ou désactiver l'URL d'origine personnalisée" | ||||
|                 }, | ||||
|                 "rewriteUrl": { | ||||
|                     "label": "URL d'origine personnalisée", | ||||
|                     "placeholder": "Entrez l'URL d'origine personnalisée" | ||||
|                 }, | ||||
|                 "help": "Si vous avez des problèmes de connexion avec OLLAMA sur Page Assist, vous pouvez configurer une URL d'origine personnalisée. Pour en savoir plus sur la configuration, <anchor>cliquez ici</anchor>." | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "manageSearch": { | ||||
|         "title": "Gérer la recherche Web", | ||||
|         "heading": "Configurer la recherche Web" | ||||
|     }, | ||||
|     "about": { | ||||
|         "title": "À propos", | ||||
|         "heading": "À propos", | ||||
|         "chromeVersion": "Version de Page Assist", | ||||
|         "ollamaVersion": "Version de Ollama", | ||||
|         "support": "Vous pouvez supporter le projet Page Assist en donnant ou parrainant via les plateformes suivantes:", | ||||
|         "koFi": "Supporter sur ko-fi", | ||||
|         "githubSponsor": "Sponsoriser sur github", | ||||
|         "githubRepo": "Référentiel GitHub" | ||||
|     }, | ||||
|     "manageKnowledge": { | ||||
|         "title": "Gérer les connaissances", | ||||
|         "heading": "Configurer la base de connaissances" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										7
									
								
								src/assets/locale/fr/sidepanel.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/assets/locale/fr/sidepanel.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| { | ||||
|     "tooltip": { | ||||
|         "embed": "Cela peut prendre quelques minutes pour intégrer la page. S'il vous plaît, patientez...", | ||||
|         "clear": "Effacer l'historique du chat", | ||||
|         "history": "Historique du chat" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										88
									
								
								src/assets/locale/it/common.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/assets/locale/it/common.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,88 @@ | ||||
| { | ||||
|     "pageAssist": "Page Assist", | ||||
|     "selectAModel": "Seleziona un Modello", | ||||
|     "save": "Salva", | ||||
|     "saved": "Salvato", | ||||
|     "cancel": "Annulla", | ||||
|     "retry": "Riprova", | ||||
|     "share": { | ||||
|         "tooltip": { | ||||
|             "share": "Condividi" | ||||
|         }, | ||||
|         "modal": { | ||||
|             "title": "Condividi Collegamento alla Chat" | ||||
|         }, | ||||
|         "form": { | ||||
|             "defaultValue": { | ||||
|                 "name": "Anonimo", | ||||
|                 "title": "Chat Senza Titolo" | ||||
|             }, | ||||
|             "title": { | ||||
|                 "label": "Titolo della Chat", | ||||
|                 "placeholder": "Inserisci il Titolo della Chat", | ||||
|                 "required": "Titolo della Chat obbligatorio" | ||||
|             }, | ||||
|             "name": { | ||||
|                 "label": "Il tuo Nome", | ||||
|                 "placeholder": "Inserisci il tuo Nome", | ||||
|                 "required": "Nome obbligatorio" | ||||
|             }, | ||||
|             "btn": { | ||||
|                 "save": "Genera Link", | ||||
|                 "saving": "Sto generando il Link..." | ||||
|             } | ||||
|         }, | ||||
|         "notification": { | ||||
|             "successGenerate": "Link copiato negli appunti", | ||||
|             "failGenerate": "Impossibile generare il link" | ||||
|         } | ||||
|     }, | ||||
|     "copyToClipboard": "Copia negli Appunti", | ||||
|     "webSearch": "Ricerca nel Web", | ||||
|     "regenerate": "Rigenera", | ||||
|     "edit": "Modifica", | ||||
|     "saveAndSubmit": "Salva e Invia", | ||||
|     "editMessage": { | ||||
|         "placeholder": "Scrivi un messaggio..." | ||||
|     }, | ||||
|     "submit": "Invia", | ||||
|     "noData": "Nessun Dato", | ||||
|     "noHistory": "Nessuna Cronologia Chat", | ||||
|     "chatWithCurrentPage": "Chatta con la Pagina Corrente", | ||||
|     "beta": "Beta", | ||||
|     "tts": "Leggi ad Alta Voce", | ||||
|     "currentChatModelSettings": "Impostazioni del Modello Corrente", | ||||
|     "modelSettings": { | ||||
|         "label": "Impostazioni del Modello", | ||||
|         "description": "Imposta le opzioni del modello globalmente per tutte le chat", | ||||
|         "form": { | ||||
|             "keepAlive": { | ||||
|                 "label": "Keep Alive", | ||||
|                 "help": "Imposta il tempo per cui il modello deve rimanere caricato in memoria (default: 5m)", | ||||
|                 "placeholder": "Inserisci la durata del Keep Alive (e.g. 5m, 10m, 1h)" | ||||
|             }, | ||||
|             "temperature": { | ||||
|                 "label": "Temperatura", | ||||
|                 "placeholder": "Inserisci la Temperatura (e.g. 0.7, 1.0)" | ||||
|             }, | ||||
|             "numCtx": { | ||||
|                 "label": "Dimensione del Contesto", | ||||
|                 "placeholder": "Inserisci la Dimensione del Contesto (default: 2048)" | ||||
|             }, | ||||
|             "seed": { | ||||
|                 "label": "Seed", | ||||
|                 "placeholder": "Inserisci il Valore Seed (e.g. 1234)", | ||||
|                 "help": "Riproducibilità dell'output del modello" | ||||
|             }, | ||||
|             "topK": { | ||||
|                 "label": "Top K", | ||||
|                 "placeholder": "Inserisci il Valore Top K (e.g. 40, 100)" | ||||
|             }, | ||||
|             "topP": { | ||||
|                 "label": "Top P", | ||||
|                 "placeholder": "Inserisci il Valore Top P (e.g. 0.9, 0.95)" | ||||
|             } | ||||
|         }, | ||||
|         "advanced": "Altre Impostazioni del Modello" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										42
									
								
								src/assets/locale/it/knowledge.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								src/assets/locale/it/knowledge.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,42 @@ | ||||
| { | ||||
|     "addBtn": "Aggiungi nuova Knowledge Base", | ||||
|     "columns": { | ||||
|         "title": "Titolo", | ||||
|         "status": "Stato", | ||||
|         "embeddings": "Modello di Embedding", | ||||
|         "createdAt": "Creato da", | ||||
|         "action": "Azioni" | ||||
|     }, | ||||
|     "expandedColumns": { | ||||
|         "name": "Nome" | ||||
|     }, | ||||
|     "tooltip": { | ||||
|         "delete": "Elimina" | ||||
|     }, | ||||
|     "confirm": { | ||||
|         "delete": "Sei sicuro di voler eliminare questa Knowledge Base?" | ||||
|     }, | ||||
|     "deleteSuccess": "Knowledge Base eliminata correttamente", | ||||
|     "status": { | ||||
|         "pending": "In attesa", | ||||
|         "finished": "Completato", | ||||
|         "processing": "In corso" | ||||
|     }, | ||||
|     "addKnowledge": "Aggiungi Knowledge Base", | ||||
|     "form": { | ||||
|         "title": { | ||||
|             "label": "Titolo Knowledge Base", | ||||
|             "placeholder": "Inserisci il titolo della Knowledge Base", | ||||
|             "required": "Il Titolo è obbligatorio" | ||||
|         }, | ||||
|         "uploadFile": { | ||||
|             "label": "Carica File", | ||||
|             "uploadText": "Trascina un file qui or scegli upload", | ||||
|             "uploadHint": "Tipi di file supportati: .pdf, .csv, .txt, .md, .docx", | ||||
|             "required": "File è obbligatorio" | ||||
|         }, | ||||
|         "submit": "Invia", | ||||
|         "success": "Knowledge Base aggiunta correttamente" | ||||
|     }, | ||||
|     "noEmbeddingModel": "Aggiungi prima un modello dalla pagina di impostazione di Ollama" | ||||
| } | ||||
							
								
								
									
										12
									
								
								src/assets/locale/it/option.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/assets/locale/it/option.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,12 @@ | ||||
| { | ||||
|     "newChat": "Nuova Chat", | ||||
|     "selectAPrompt": "Scegli un Prompt", | ||||
|     "githubRepository": "GitHub Repository", | ||||
|     "settings": "Impsotazioni", | ||||
|     "sidebarTitle": "Cronologia Chat", | ||||
|     "error": "Errore", | ||||
|     "somethingWentWrong": "Qualcosa è andato storto", | ||||
|     "validationSelectModel": "Scegliere un modello per continuare", | ||||
|     "deleteHistoryConfirmation": "Sei sicuro che vuoi eliminare la cronologia?", | ||||
|     "editHistoryTitle": "Inserisci un nuovo titolo" | ||||
| } | ||||
							
								
								
									
										29
									
								
								src/assets/locale/it/playground.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								src/assets/locale/it/playground.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,29 @@ | ||||
| { | ||||
|     "ollamaState": { | ||||
|         "searching": "Sto cercando Ollama 🦙", | ||||
|         "running": "Ollama è attivo 🦙", | ||||
|         "notRunning": "Impossibile connettersi a Ollama 🦙", | ||||
|         "connectionError": "C'è stato un problema di connessione. Controlla la <anchor>documentazione</anchor> per investigare." | ||||
|     }, | ||||
|     "formError": { | ||||
|         "noModel": "Seleziona un modello", | ||||
|         "noEmbeddingModel": "Imposta un modello di embedding da Impostazioni > Ollama" | ||||
|     }, | ||||
|     "form": { | ||||
|         "textarea": { | ||||
|             "placeholder": "Scrivi un messaggio..." | ||||
|         }, | ||||
|         "webSearch": { | ||||
|             "on": "Attivo", | ||||
|             "off": "Disattivato" | ||||
|         } | ||||
|     }, | ||||
|     "tooltip": { | ||||
|         "searchInternet": "Cerca su Internet", | ||||
|         "speechToText": "Speech to Text", | ||||
|         "uploadImage": "Carica immagine", | ||||
|         "stopStreaming": "Ferma lo Streaming", | ||||
|         "knowledge": "Conoscenza" | ||||
|     }, | ||||
|     "sendWhenEnter": "Invia subito dopo Enter" | ||||
| } | ||||
							
								
								
									
										286
									
								
								src/assets/locale/it/settings.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										286
									
								
								src/assets/locale/it/settings.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,286 @@ | ||||
| { | ||||
|     "generalSettings": { | ||||
|         "title": "Impostazioni Generali", | ||||
|         "settings": { | ||||
|             "heading": "Impostazioni Web UI", | ||||
|             "speechRecognitionLang": { | ||||
|                 "label": "Lingua per il riconoscimento vocale", | ||||
|                 "placeholder": "Scegli una lingua" | ||||
|             }, | ||||
|             "language": { | ||||
|                 "label": "Lingua", | ||||
|                 "placeholder": "Scegli una lingua" | ||||
|             }, | ||||
|             "darkMode": { | ||||
|                 "label": "Cambia il Tema", | ||||
|                 "options": { | ||||
|                     "light": "Chiaro", | ||||
|                     "dark": "Scuro" | ||||
|                 } | ||||
|             }, | ||||
|             "copilotResumeLastChat": { | ||||
|                 "label": "Riprendi l'ultima chat quando apri il Pannello Laterale  (Copilot)" | ||||
|             }, | ||||
|             "hideCurrentChatModelSettings": { | ||||
|                 "label": "Nascondi le impostazioni correnti del modello Chat" | ||||
|             } | ||||
|         }, | ||||
|         "webSearch": { | ||||
|             "heading": "Gestione ricerca Web", | ||||
|             "searchMode": { | ||||
|                 "label": "Effettua ricerca web Internet semplice" | ||||
|             }, | ||||
|             "provider": { | ||||
|                 "label": "Motori di ricerca", | ||||
|                 "placeholder": "Scegli un motore di ricerca" | ||||
|             }, | ||||
|             "totalSearchResults": { | ||||
|                 "label": "Risultati della ricerca", | ||||
|                 "placeholder": "Inserisci il totale delle ricerche" | ||||
|             } | ||||
|         }, | ||||
|         "system": { | ||||
|             "heading": "Impostazioni di Sistema", | ||||
|             "deleteChatHistory": { | ||||
|                 "label": "Elimina cronologia Chat", | ||||
|                 "button": "Elimina", | ||||
|                 "confirm": "Sei sicuro che vuoi eliminare la tua cronologia delle chat? Questa azione non può essere annullata." | ||||
|             }, | ||||
|             "export": { | ||||
|                 "label": "Esporta la cronologia Chat, Base di Conoscenza, e Prompts", | ||||
|                 "button": "Esporta Dati", | ||||
|                 "success": "Esportato con Successo" | ||||
|             }, | ||||
|             "import": { | ||||
|                 "label": "Imposta la cronologia Chat, Base di Conoscenza, e Prompts", | ||||
|                 "button": "Importa Dati", | ||||
|                 "success": "Importato con Successo", | ||||
|                 "error": "Errore Importazione" | ||||
|             } | ||||
|         }, | ||||
|         "tts": { | ||||
|             "heading": "Impostazioni Text-to-Speech", | ||||
|             "ttsEnabled": { | ||||
|                 "label": "Abilita Text-to-Speech" | ||||
|             }, | ||||
|             "ttsProvider": { | ||||
|                 "label": "Text-to-Speech Provider", | ||||
|                 "placeholder": "Seleziona un provider" | ||||
|             }, | ||||
|             "ttsVoice": { | ||||
|                 "label": "Text-to-Speech Voce", | ||||
|                 "placeholder": "Seleziona una voce" | ||||
|             }, | ||||
|             "ssmlEnabled": { | ||||
|                 "label": "Abilita SSML (Speech Synthesis Markup Language)" | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "manageModels": { | ||||
|         "title": "Gestione Modelli", | ||||
|         "addBtn": "Aggiungi un nuovo Modello", | ||||
|         "columns": { | ||||
|             "name": "Nome", | ||||
|             "digest": "Digest", | ||||
|             "modifiedAt": "Modificato il", | ||||
|             "size": "Dimensioni", | ||||
|             "actions": "Azioni" | ||||
|         }, | ||||
|         "expandedColumns": { | ||||
|             "parentModel": "Modello Padre", | ||||
|             "format": "Formato", | ||||
|             "family": "Famiglia", | ||||
|             "parameterSize": "Numero di Parametri", | ||||
|             "quantizationLevel": "Livello di Quantizzazione" | ||||
|         }, | ||||
|         "tooltip": { | ||||
|             "delete": "Elimina Modello", | ||||
|             "repull": "Ri-Scarica Modello" | ||||
|         }, | ||||
|         "confirm": { | ||||
|             "delete": "Sei sicuro di voler eliminare questo modello?", | ||||
|             "repull": "Se sicuro che vuoi ri-scaricare questo modello?" | ||||
|         }, | ||||
|         "modal": { | ||||
|             "title": "Aggiungi Nuovo Modello", | ||||
|             "placeholder": "Inserisci il Nome Modello", | ||||
|             "pull": "Scarico del Modello" | ||||
|         }, | ||||
|         "notification": { | ||||
|             "pullModel": "Scarico del Modello", | ||||
|             "pullModelDescription": "Scaricando il modello {{modelName}}. Per ulteriori dettagli visualizza l'icona dell'estensione.", | ||||
|             "success": "Completato", | ||||
|             "error": "Errore", | ||||
|             "successDescription": "Scarico del modello completato", | ||||
|             "successDeleteDescription": "Eliminazione del modello completato", | ||||
|             "someError": "Qualcosa è andato storto. Riprova più tardi" | ||||
|         } | ||||
|     }, | ||||
|     "managePrompts": { | ||||
|         "title": "Gestisci Prompts", | ||||
|         "addBtn": "Aggiungi nuovo Prompt", | ||||
|         "option1": "Normale", | ||||
|         "option2": "RAG", | ||||
|         "questionPrompt": "Question Prompt", | ||||
|         "columns": { | ||||
|             "title": "Titolo", | ||||
|             "prompt": "Prompt", | ||||
|             "type": "Tipo di Prompt", | ||||
|             "actions": "Azioni" | ||||
|         }, | ||||
|         "systemPrompt": "Prompt di Sistema", | ||||
|         "quickPrompt": "Prompt Veloce", | ||||
|         "tooltip": { | ||||
|             "delete": "Elimina Prompt", | ||||
|             "edit": "Modifica Prompt" | ||||
|         }, | ||||
|         "confirm": { | ||||
|             "delete": "Sei sicuro di voler eliminare questo prompt? L'azione non può essere annullata." | ||||
|         }, | ||||
|         "modal": { | ||||
|             "addTitle": "Aggiungi Nuovo Prompt", | ||||
|             "editTitle": "Modifica Prompt" | ||||
|         }, | ||||
|         "form": { | ||||
|             "title": { | ||||
|                 "label": "Titolo", | ||||
|                 "placeholder": "I Miei Prompt", | ||||
|                 "required": "Inserisci il Titolo" | ||||
|             }, | ||||
|             "prompt": { | ||||
|                 "label": "Prompt", | ||||
|                 "placeholder": "Inserisci Prompt", | ||||
|                 "required": "Scrivi il prompt", | ||||
|                 "help": "Puoi usare {key} come variabile nel tuo prompt." | ||||
|             }, | ||||
|             "isSystem": { | ||||
|                 "label": "Prompt di Sistema" | ||||
|             }, | ||||
|             "btnSave": { | ||||
|                 "saving": "Aggiungendo Prompt...", | ||||
|                 "save": "Aggiungi Prompt" | ||||
|             }, | ||||
|             "btnEdit": { | ||||
|                 "saving": "Aggiornando Prompt...", | ||||
|                 "save": "Aggiorna Prompt" | ||||
|             } | ||||
|         }, | ||||
|         "notification": { | ||||
|             "addSuccess": "Prompt Aggiunto", | ||||
|             "addSuccessDesc": "Il Prompt è stato aggiunto correttamente", | ||||
|             "error": "Errore", | ||||
|             "someError": "Qualcosa è andato storto. Riprova più tardi", | ||||
|             "updatedSuccess": "Prompt Aggiornato", | ||||
|             "updatedSuccessDesc": "Il Prompt è stato aggiornato correttmante", | ||||
|             "deletedSuccess": "Prompt Eliminato", | ||||
|             "deletedSuccessDesc": "Il Prompt è stato eliminato correttamente" | ||||
|         } | ||||
|     }, | ||||
|     "manageShare": { | ||||
|         "title": "Gestione Condivisioni", | ||||
|         "heading": "Configura l'URL della Pagina di Condivisione", | ||||
|         "form": { | ||||
|             "url": { | ||||
|                 "label": "URL Pagina di Condivisione", | ||||
|                 "placeholder": "Inserisci URL Pagina di Condivisione", | ||||
|                 "required": "Inserisci l'url della pagina di condivisione!", | ||||
|                 "help": "Per ragioni di  privacy, tu puoi ospitare in self-host la paginacon il seguente URL. <anchor>Leggi altro</anchor>." | ||||
|             } | ||||
|         }, | ||||
|         "webshare": { | ||||
|             "heading": "Condivisioni Web", | ||||
|             "columns": { | ||||
|                 "title": "Titolo", | ||||
|                 "url": "URL", | ||||
|                 "actions": "Azioni" | ||||
|             }, | ||||
|             "tooltip": { | ||||
|                 "delete": "Elimina Condivisione" | ||||
|             }, | ||||
|             "confirm": { | ||||
|                 "delete": "Sei sicuro che vuoi eliminare questa condivisione? L'azione non può essere annullata." | ||||
|             }, | ||||
|             "label": "Gestione Condivisioni", | ||||
|             "description": "Abilita o Disattiva la funzionalità di condivisione" | ||||
|         }, | ||||
|         "notification": { | ||||
|             "pageShareSuccess": " URL di condivisione aggiornato correttamente", | ||||
|             "someError": "Qualcosa è andato storto. Riprova più tardi", | ||||
|             "webShareDeleteSuccess": "Condivisione eliminata correttamente" | ||||
|         } | ||||
|     }, | ||||
|     "ollamaSettings": { | ||||
|         "title": "Impostazioni Ollama", | ||||
|         "heading": "Configura Ollama", | ||||
|         "settings": { | ||||
|             "ollamaUrl": { | ||||
|                 "label": "Ollama URL", | ||||
|                 "placeholder": "Inserici l'URL di Ollama" | ||||
|             }, | ||||
|             "ragSettings": { | ||||
|                 "label": "Impostazioni RAG", | ||||
|                 "model": { | ||||
|                     "label": "Modello di Embedding", | ||||
|                     "required": "Scegliere il modello", | ||||
|                     "help": "E' raccomandato l'uso di modelli come `nomic-embed-text`.", | ||||
|                     "placeholder": "Seleziona un modello" | ||||
|                 }, | ||||
|                 "chunkSize": { | ||||
|                     "label": "Dimensione del Blocco (Chunk Size)", | ||||
|                     "placeholder": "Inserisci la Dimensione del Blocco (Chunk Size)", | ||||
|                     "required": "Inserisci la Dimensione del Blocco (chunk size)" | ||||
|                 }, | ||||
|                 "chunkOverlap": { | ||||
|                     "label": "Sovrapposizione del Blocco (Chunk Overlap)", | ||||
|                     "placeholder": "Inserisci la Sovrapposizione del Blocco (Chunk Overlap)", | ||||
|                     "required": "Inserisci la Sovrapposizione del Blocco" | ||||
|                 } | ||||
|             }, | ||||
|             "prompt": { | ||||
|                 "label": "Configura il Prompt RAG", | ||||
|                 "option1": "Normale", | ||||
|                 "option2": "Web", | ||||
|                 "alert": "La configurazione del prompt di sistema qui è deprecato. Usa la sezione Gestione Prompt per aggiungere o modificare i prompts.Questa sezione sarà eliminata nelle prossime release", | ||||
|                 "systemPrompt": "Prompt di Sistema", | ||||
|                 "systemPromptPlaceholder": "Inserisci il Prompt di Sistema", | ||||
|                 "webSearchPrompt": "Prompt per la Ricerca Web", | ||||
|                 "webSearchPromptHelp": "Non rimuovere `{search_results}` dal prompt.", | ||||
|                 "webSearchPromptError": "Inserisci il prompt per la ricerca web", | ||||
|                 "webSearchPromptPlaceholder": "Imserosco il Prompt per la Ricerca Web", | ||||
|                 "webSearchFollowUpPrompt": "Prompt di Follow Up sulla Ricerca Web", | ||||
|                 "webSearchFollowUpPromptHelp": "Non rimuovere `{chat_history}` e `{question}` dal prompt.", | ||||
|                 "webSearchFollowUpPromptError": "Inserisci il Prompt di Follow Up della Ricerca Web!", | ||||
|                 "webSearchFollowUpPromptPlaceholder": "I tuoi Prompt di Follow Up delle Ricerche Web" | ||||
|             }, | ||||
|             "advanced": { | ||||
|                 "label": "Configurazione Avanzata Ollama URL", | ||||
|                 "urlRewriteEnabled": { | ||||
|                     "label": "Abilita o Disabilita l'URL di Origine Personalizzato" | ||||
|                 }, | ||||
|                 "rewriteUrl": { | ||||
|                     "label": "URL di Origine Personalizzato", | ||||
|                     "placeholder": "Inserisci URL di Origine Personalizzato" | ||||
|                 }, | ||||
|                 "help": "Se hai problemi di connessione con Ollama su Page Assist, puoi configurare un URL di origine personalizzato. Per saperne di più sulla configurazione, <anchor>clicca qui</anchor>." | ||||
|             } | ||||
|         } | ||||
|     }, | ||||
|     "manageSearch": { | ||||
|         "title": "Gestisci Ricerca Web", | ||||
|         "heading": "Configura Ricerca Web" | ||||
|     }, | ||||
|     "about": { | ||||
|         "title": "Informazioni", | ||||
|         "heading": "Informazioni", | ||||
|         "chromeVersion": "Versione di Page Assist", | ||||
|         "ollamaVersion": "Versione di Ollama", | ||||
|         "support": "Puoi supportare il progetto Page Assist donando o sponsorizzando attraverso le seguenti piattaforme:", | ||||
|         "koFi": "Supporta su Ko-fi", | ||||
|         "githubSponsor": "Sponsorizza su GitHub", | ||||
|         "githubRepo": "Repository GitHub" | ||||
|     }, | ||||
|     "manageKnowledge": { | ||||
|         "title": "Gestisci Conoscenza", | ||||
|         "heading": "Configura Base di Conoscenza" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										7
									
								
								src/assets/locale/it/sidepanel.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/assets/locale/it/sidepanel.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,7 @@ | ||||
| { | ||||
|     "tooltip": { | ||||
|         "embed": "L'inserimento della pagina potrebbe richiedere alcuni minuti. Attendere prego...", | ||||
|         "clear": "Cancella la cronologia della chat", | ||||
|         "history": "Cronologia della chat" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										66
									
								
								src/components/Common/CodeBlock.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										66
									
								
								src/components/Common/CodeBlock.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,66 @@ | ||||
| import { Tooltip } from "antd" | ||||
| import { CheckIcon, ClipboardIcon } from "lucide-react" | ||||
| import { FC, memo, useState } from "react" | ||||
| import { useTranslation } from "react-i18next" | ||||
| import { Prism as SyntaxHighlighter } from "react-syntax-highlighter" | ||||
| import { coldarkDark } from "react-syntax-highlighter/dist/cjs/styles/prism" | ||||
| 
 | ||||
| interface Props { | ||||
|   language: string | ||||
|   value: string | ||||
| } | ||||
| 
 | ||||
| export const CodeBlock: FC<Props> = memo(({ language, value }) => { | ||||
|   const [isBtnPressed, setIsBtnPressed] = useState(false) | ||||
|   const { t } = useTranslation("common") | ||||
|   return ( | ||||
|     <> | ||||
|       <div className="code relative text-base font-sans codeblock bg-zinc-950  rounded-md overflow-hidden"> | ||||
|         <div className="flex bg-gray-800 items-center justify-between py-1.5 px-4"> | ||||
|           <span className="text-xs lowercase text-gray-200">{language}</span> | ||||
| 
 | ||||
|           <div className="flex items-center"> | ||||
|             <Tooltip title={t("copyToClipboard")}> | ||||
|               <button | ||||
|                 onClick={() => { | ||||
|                   navigator.clipboard.writeText(value) | ||||
|                   setIsBtnPressed(true) | ||||
|                   setTimeout(() => { | ||||
|                     setIsBtnPressed(false) | ||||
|                   }, 4000) | ||||
|                 }} | ||||
|                 className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-200 hover:bg-gray-700 hover:text-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 focus:ring-offset-gray-100"> | ||||
|                 {!isBtnPressed ? ( | ||||
|                   <ClipboardIcon className="h-4 w-4" /> | ||||
|                 ) : ( | ||||
|                   <CheckIcon className="h-4 w-4 text-green-400" /> | ||||
|                 )} | ||||
|               </button> | ||||
|             </Tooltip> | ||||
|           </div> | ||||
|         </div> | ||||
|         <SyntaxHighlighter | ||||
|           language={language} | ||||
|           style={coldarkDark} | ||||
|           PreTag="div" | ||||
|           customStyle={{ | ||||
|             margin: 0, | ||||
|             width: "100%", | ||||
|             background: "transparent", | ||||
|             padding: "1.5rem 1rem" | ||||
|           }} | ||||
|           lineNumberStyle={{ | ||||
|             userSelect: "none" | ||||
|           }} | ||||
|           codeTagProps={{ | ||||
|             style: { | ||||
|               fontSize: "0.9rem", | ||||
|               fontFamily: "var(--font-mono)" | ||||
|             } | ||||
|           }}> | ||||
|           {value} | ||||
|         </SyntaxHighlighter> | ||||
|       </div> | ||||
|     </> | ||||
|   ) | ||||
| }) | ||||
| @ -1,68 +1,38 @@ | ||||
| import { Prism as SyntaxHighlighter } from "react-syntax-highlighter" | ||||
| import remarkGfm from "remark-gfm" | ||||
| import { nightOwl } from "react-syntax-highlighter/dist/cjs/styles/prism" | ||||
| import remarkMath from "remark-math" | ||||
| import ReactMarkdown from "react-markdown" | ||||
| import ReactMarkdown, { Options } from "react-markdown" | ||||
| 
 | ||||
| import "property-information" | ||||
| import React from "react" | ||||
| import { Tooltip } from "antd" | ||||
| import { CheckIcon, ClipboardIcon } from "lucide-react" | ||||
| import { useTranslation } from "react-i18next" | ||||
| 
 | ||||
| import { FC, memo } from "react" | ||||
| import { CodeBlock } from "./CodeBlock" | ||||
| 
 | ||||
| export const MemoizedReactMarkdown: FC<Options> = memo( | ||||
|   ReactMarkdown, | ||||
|   (prevProps, nextProps) => | ||||
|     prevProps.children === nextProps.children && | ||||
|     prevProps.className === nextProps.className | ||||
| ) | ||||
| 
 | ||||
| export default function Markdown({ message }: { message: string }) { | ||||
|   const [isBtnPressed, setIsBtnPressed] = React.useState(false) | ||||
|   const { t } = useTranslation("common") | ||||
| 
 | ||||
|   return ( | ||||
|     <React.Fragment> | ||||
|       <ReactMarkdown | ||||
|       <MemoizedReactMarkdown | ||||
|         className="prose break-words dark:prose-invert prose-p:leading-relaxed prose-pre:p-0 dark:prose-dark" | ||||
|         remarkPlugins={[remarkGfm, remarkMath]} | ||||
|         components={{ | ||||
|           code({ node, inline, className, children, ...props }) { | ||||
|             const match = /language-(\w+)/.exec(className || "") | ||||
|             return !inline ? ( | ||||
|               <div className="code relative text-base bg-gray-800 rounded-md overflow-hidden"> | ||||
|                 <div className="flex items-center justify-between py-1.5 px-4"> | ||||
|                   <span className="text-xs lowercase text-gray-200"> | ||||
|                     {className && className.replace("language-", "")} | ||||
|                   </span> | ||||
| 
 | ||||
|                   <div className="flex items-center"> | ||||
|                     <Tooltip title={t("copyToClipboard")}> | ||||
|                       <button | ||||
|                         onClick={() => { | ||||
|                           navigator.clipboard.writeText(children[0] as string) | ||||
|                           setIsBtnPressed(true) | ||||
|                           setTimeout(() => { | ||||
|                             setIsBtnPressed(false) | ||||
|                           }, 4000) | ||||
|                         }} | ||||
|                         className="flex gap-1.5 items-center rounded bg-none p-1 text-xs text-gray-200 hover:bg-gray-700 hover:text-gray-100 focus:outline-none focus:ring-2 focus:ring-gray-500 focus:ring-offset-2 focus:ring-offset-gray-100"> | ||||
|                         {!isBtnPressed ? ( | ||||
|                           <ClipboardIcon className="h-4 w-4" /> | ||||
|                         ) : ( | ||||
|                           <CheckIcon className="h-4 w-4 text-green-400" /> | ||||
|                         )} | ||||
|                       </button> | ||||
|                     </Tooltip> | ||||
|                   </div> | ||||
|                 </div> | ||||
|                 <SyntaxHighlighter | ||||
|                   {...props} | ||||
|                   children={String(children).replace(/\n$/, "")} | ||||
|                   style={nightOwl} | ||||
|                   key={Math.random()} | ||||
|                   customStyle={{ | ||||
|                     margin: 0, | ||||
|                     fontSize: "1rem", | ||||
|                     lineHeight: "1.5rem" | ||||
|                   }} | ||||
|                   language={(match && match[1]) || ""} | ||||
|                   codeTagProps={{ | ||||
|                     className: "text-sm" | ||||
|                   }} | ||||
|                 /> | ||||
|               </div> | ||||
|             <CodeBlock | ||||
|               language={match ? match[1] : ""} | ||||
|               value={String(children).replace(/\n$/, "")} | ||||
|             /> | ||||
|             ) : ( | ||||
|               <code className={`${className} font-semibold`} {...props}> | ||||
|                 {children} | ||||
| @ -85,7 +55,7 @@ export default function Markdown({ message }: { message: string }) { | ||||
|           } | ||||
|         }}> | ||||
|         {message} | ||||
|       </ReactMarkdown> | ||||
|       </MemoizedReactMarkdown> | ||||
|     </React.Fragment> | ||||
|   ) | ||||
| } | ||||
|  | ||||
| @ -49,7 +49,7 @@ export const EditMessageForm = (props: Props) => { | ||||
|       <div className="flex justify-center space-x-2 mt-2"> | ||||
|         <button | ||||
|           aria-label={t("save")} | ||||
|           className="bg-white dark:bg-black px-2.5 py-2 rounded-md text-gray-700 dark:text-gray-300 focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-500 hover:bg-gray-100 dark:hover:bg-gray-900"> | ||||
|           className="bg-black px-2.5 py-2 rounded-md text-white focus:outline-none focus-visible:ring-2 focus-visible:ring-offset-2 focus-visible:ring-gray-500 hover:bg-gray-900"> | ||||
|           {props.isBot ? t("save") : t("saveAndSubmit")} | ||||
|         </button> | ||||
|         <button | ||||
|  | ||||
							
								
								
									
										221
									
								
								src/components/Layouts/Header.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										221
									
								
								src/components/Layouts/Header.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,221 @@ | ||||
| import { useStorage } from "@plasmohq/storage/hook" | ||||
| import { | ||||
|   BrainCog, | ||||
|   ChevronLeft, | ||||
|   CogIcon, | ||||
|   ComputerIcon, | ||||
|   GithubIcon, | ||||
|   PanelLeftIcon, | ||||
|   SquarePen, | ||||
|   ZapIcon | ||||
| } from "lucide-react" | ||||
| import { useTranslation } from "react-i18next" | ||||
| import { useLocation, NavLink } from "react-router-dom" | ||||
| import { OllamaIcon } from "../Icons/Ollama" | ||||
| import { SelectedKnowledge } from "../Option/Knowledge/SelectedKnwledge" | ||||
| import { ModelSelect } from "../Common/ModelSelect" | ||||
| import { PromptSelect } from "../Common/PromptSelect" | ||||
| import { useQuery } from "@tanstack/react-query" | ||||
| import { fetchChatModels } from "~/services/ollama" | ||||
| import { useMessageOption } from "~/hooks/useMessageOption" | ||||
| import { Select, Tooltip } from "antd" | ||||
| import { getAllPrompts } from "@/db" | ||||
| import { ShareBtn } from "~/components/Common/ShareBtn" | ||||
| type Props = { | ||||
|   setSidebarOpen: (open: boolean) => void | ||||
|   setOpenModelSettings: (open: boolean) => void | ||||
| } | ||||
| 
 | ||||
| export const Header: React.FC<Props> = ({ | ||||
|   setOpenModelSettings, | ||||
|   setSidebarOpen | ||||
| }) => { | ||||
|   const { t } = useTranslation(["option", "common"]) | ||||
|   const [shareModeEnabled] = useStorage("shareMode", false) | ||||
|   const [hideCurrentChatModelSettings] = useStorage( | ||||
|     "hideCurrentChatModelSettings", | ||||
|     false | ||||
|   ) | ||||
|   const { | ||||
|     selectedModel, | ||||
|     setSelectedModel, | ||||
|     clearChat, | ||||
|     selectedSystemPrompt, | ||||
|     setSelectedQuickPrompt, | ||||
|     setSelectedSystemPrompt, | ||||
|     messages, | ||||
|     streaming | ||||
|   } = useMessageOption() | ||||
|   const { | ||||
|     data: models, | ||||
|     isLoading: isModelsLoading, | ||||
|     isFetching: isModelsFetching | ||||
|   } = useQuery({ | ||||
|     queryKey: ["fetchModel"], | ||||
|     queryFn: () => fetchChatModels({ returnEmpty: true }), | ||||
|     refetchInterval: 15000 | ||||
|   }) | ||||
| 
 | ||||
|   const { data: prompts, isLoading: isPromptLoading } = useQuery({ | ||||
|     queryKey: ["fetchAllPromptsLayout"], | ||||
|     queryFn: getAllPrompts | ||||
|   }) | ||||
| 
 | ||||
|   const { pathname } = useLocation() | ||||
| 
 | ||||
|   const getPromptInfoById = (id: string) => { | ||||
|     return prompts?.find((prompt) => prompt.id === id) | ||||
|   } | ||||
| 
 | ||||
|   const handlePromptChange = (value?: string) => { | ||||
|     if (!value) { | ||||
|       setSelectedSystemPrompt(undefined) | ||||
|       setSelectedQuickPrompt(undefined) | ||||
|       return | ||||
|     } | ||||
|     const prompt = getPromptInfoById(value) | ||||
|     if (prompt?.is_system) { | ||||
|       setSelectedSystemPrompt(prompt.id) | ||||
|     } else { | ||||
|       setSelectedSystemPrompt(undefined) | ||||
|       setSelectedQuickPrompt(prompt!.content) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return ( | ||||
|     <div className="sticky top-0 z-[999] flex h-16 p-3  bg-gray-50 border-b  dark:bg-[#171717] dark:border-gray-600"> | ||||
|       <div className="flex gap-2 items-center"> | ||||
|         {pathname !== "/" && ( | ||||
|           <div> | ||||
|             <NavLink | ||||
|               to="/" | ||||
|               className="text-gray-500 items-center dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"> | ||||
|               <ChevronLeft className="w-4 h-4" /> | ||||
|             </NavLink> | ||||
|           </div> | ||||
|         )} | ||||
|         <div> | ||||
|           <button | ||||
|             className="text-gray-500 dark:text-gray-400" | ||||
|             onClick={() => setSidebarOpen(true)}> | ||||
|             <PanelLeftIcon className="w-6 h-6" /> | ||||
|           </button> | ||||
|         </div> | ||||
|         <div> | ||||
|           <button | ||||
|             onClick={clearChat} | ||||
|             className="inline-flex  dark:bg-transparent bg-white items-center rounded-lg border  dark:border-gray-700 bg-transparent px-3 py-2.5 text-xs lg:text-sm font-medium leading-4 text-gray-800  dark:text-white disabled:opacity-50 ease-in-out transition-colors duration-200 hover:bg-gray-100 dark:hover:bg-gray-800 dark:hover:text-white"> | ||||
|             <SquarePen className="h-5 w-5 " /> | ||||
|             <span className=" truncate ml-3">{t("newChat")}</span> | ||||
|           </button> | ||||
|         </div> | ||||
|         <span className="text-lg font-thin text-zinc-300 dark:text-zinc-600"> | ||||
|           {"/"} | ||||
|         </span> | ||||
|         <div className="hidden lg:block"> | ||||
|           <Select | ||||
|             value={selectedModel} | ||||
|             onChange={(e) => { | ||||
|               setSelectedModel(e) | ||||
|               localStorage.setItem("selectedModel", e) | ||||
|             }} | ||||
|             size="large" | ||||
|             loading={isModelsLoading || isModelsFetching} | ||||
|             filterOption={(input, option) => | ||||
|               option.label.key.toLowerCase().indexOf(input.toLowerCase()) >= 0 | ||||
|             } | ||||
|             showSearch | ||||
|             placeholder={t("common:selectAModel")} | ||||
|             className="w-72" | ||||
|             options={models?.map((model) => ({ | ||||
|               label: ( | ||||
|                 <span | ||||
|                   key={model.model} | ||||
|                   className="flex flex-row gap-3 items-center truncate"> | ||||
|                   <OllamaIcon className="w-5 h-5" /> | ||||
|                   <span className="truncate">{model.name}</span> | ||||
|                 </span> | ||||
|               ), | ||||
|               value: model.model | ||||
|             }))} | ||||
|           /> | ||||
|         </div> | ||||
|         <div className="lg:hidden"> | ||||
|           <ModelSelect /> | ||||
|         </div> | ||||
|         <span className="text-lg font-thin text-zinc-300 dark:text-zinc-600"> | ||||
|           {"/"} | ||||
|         </span> | ||||
|         <div className="hidden lg:block"> | ||||
|           <Select | ||||
|             size="large" | ||||
|             loading={isPromptLoading} | ||||
|             showSearch | ||||
|             placeholder={t("selectAPrompt")} | ||||
|             className="w-60" | ||||
|             allowClear | ||||
|             onChange={handlePromptChange} | ||||
|             value={selectedSystemPrompt} | ||||
|             filterOption={(input, option) => | ||||
|               //@ts-ignore
 | ||||
|               option.label.key.toLowerCase().indexOf(input.toLowerCase()) >= 0 | ||||
|             } | ||||
|             options={prompts?.map((prompt) => ({ | ||||
|               label: ( | ||||
|                 <span | ||||
|                   key={prompt.title} | ||||
|                   className="flex flex-row gap-3 items-center"> | ||||
|                   {prompt.is_system ? ( | ||||
|                     <ComputerIcon className="w-4 h-4" /> | ||||
|                   ) : ( | ||||
|                     <ZapIcon className="w-4 h-4" /> | ||||
|                   )} | ||||
|                   {prompt.title} | ||||
|                 </span> | ||||
|               ), | ||||
|               value: prompt.id | ||||
|             }))} | ||||
|           /> | ||||
|         </div> | ||||
|         <div className="lg:hidden"> | ||||
|           <PromptSelect /> | ||||
|         </div> | ||||
|         <SelectedKnowledge /> | ||||
|       </div> | ||||
|       <div className="flex flex-1 justify-end px-4"> | ||||
|         <div className="ml-4 flex items-center md:ml-6"> | ||||
|           <div className="flex gap-4 items-center"> | ||||
|             {!hideCurrentChatModelSettings && ( | ||||
|               <Tooltip title={t("common:currentChatModelSettings")}> | ||||
|                 <button | ||||
|                   onClick={() => setOpenModelSettings(true)} | ||||
|                   className="!text-gray-500 dark:text-gray-300 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"> | ||||
|                   <BrainCog className="w-6 h-6" /> | ||||
|                 </button> | ||||
|               </Tooltip> | ||||
|             )} | ||||
|             {pathname === "/" && | ||||
|               messages.length > 0 && | ||||
|               !streaming && | ||||
|               shareModeEnabled && <ShareBtn messages={messages} />} | ||||
|             <Tooltip title={t("githubRepository")}> | ||||
|               <a | ||||
|                 href="https://github.com/n4ze3m/page-assist" | ||||
|                 target="_blank" | ||||
|                 className="!text-gray-500 hidden lg:block dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"> | ||||
|                 <GithubIcon className="w-6 h-6" /> | ||||
|               </a> | ||||
|             </Tooltip> | ||||
|             <Tooltip title={t("settings")}> | ||||
|               <NavLink | ||||
|                 to="/settings" | ||||
|                 className="!text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"> | ||||
|                 <CogIcon className="w-6 h-6" /> | ||||
|               </NavLink> | ||||
|             </Tooltip> | ||||
|           </div> | ||||
|         </div> | ||||
|       </div> | ||||
|     </div> | ||||
|   ) | ||||
| } | ||||
| @ -1,30 +1,12 @@ | ||||
| import React, { useState } from "react" | ||||
| 
 | ||||
| import { useLocation, NavLink } from "react-router-dom" | ||||
| import { Sidebar } from "../Option/Sidebar" | ||||
| import { Drawer, Select, Tooltip } from "antd" | ||||
| import { useQuery } from "@tanstack/react-query" | ||||
| import { fetchChatModels, getAllModels } from "~/services/ollama" | ||||
| import { useMessageOption } from "~/hooks/useMessageOption" | ||||
| import { | ||||
|   BrainCog, | ||||
|   ChevronLeft, | ||||
|   CogIcon, | ||||
|   ComputerIcon, | ||||
|   GithubIcon, | ||||
|   PanelLeftIcon, | ||||
|   SquarePen, | ||||
|   ZapIcon | ||||
| } from "lucide-react" | ||||
| import { getAllPrompts } from "@/db" | ||||
| import { ShareBtn } from "~/components/Common/ShareBtn" | ||||
| import { Drawer } from "antd" | ||||
| 
 | ||||
| import { useTranslation } from "react-i18next" | ||||
| import { OllamaIcon } from "../Icons/Ollama" | ||||
| import { SelectedKnowledge } from "../Option/Knowledge/SelectedKnwledge" | ||||
| import { useStorage } from "@plasmohq/storage/hook" | ||||
| import { ModelSelect } from "../Common/ModelSelect" | ||||
| import { PromptSelect } from "../Common/PromptSelect" | ||||
| 
 | ||||
| import { CurrentChatModelSettings } from "../Common/Settings/CurrentChatModelSettings" | ||||
| import { Header } from "./Header" | ||||
| 
 | ||||
| export default function OptionLayout({ | ||||
|   children | ||||
| @ -33,204 +15,16 @@ export default function OptionLayout({ | ||||
| }) { | ||||
|   const [sidebarOpen, setSidebarOpen] = useState(false) | ||||
|   const { t } = useTranslation(["option", "common"]) | ||||
|   const [shareModeEnabled] = useStorage("shareMode", false) | ||||
|   const [openModelSettings, setOpenModelSettings] = useState(false) | ||||
|   const [hideCurrentChatModelSettings] = useStorage( | ||||
|     "hideCurrentChatModelSettings", | ||||
|     false | ||||
|   ) | ||||
| 
 | ||||
|   const { | ||||
|     selectedModel, | ||||
|     setSelectedModel, | ||||
|     clearChat, | ||||
|     selectedSystemPrompt, | ||||
|     setSelectedQuickPrompt, | ||||
|     setSelectedSystemPrompt, | ||||
|     messages, | ||||
|     streaming | ||||
|   } = useMessageOption() | ||||
| 
 | ||||
|   const { | ||||
|     data: models, | ||||
|     isLoading: isModelsLoading, | ||||
|     isFetching: isModelsFetching | ||||
|   } = useQuery({ | ||||
|     queryKey: ["fetchModel"], | ||||
|     queryFn: () => fetchChatModels({ returnEmpty: true }), | ||||
|     refetchInterval: 15000 | ||||
|   }) | ||||
| 
 | ||||
|   const { data: prompts, isLoading: isPromptLoading } = useQuery({ | ||||
|     queryKey: ["fetchAllPromptsLayout"], | ||||
|     queryFn: getAllPrompts | ||||
|   }) | ||||
| 
 | ||||
|   const { pathname } = useLocation() | ||||
| 
 | ||||
|   const getPromptInfoById = (id: string) => { | ||||
|     return prompts?.find((prompt) => prompt.id === id) | ||||
|   } | ||||
| 
 | ||||
|   const handlePromptChange = (value?: string) => { | ||||
|     if (!value) { | ||||
|       setSelectedSystemPrompt(undefined) | ||||
|       setSelectedQuickPrompt(undefined) | ||||
|       return | ||||
|     } | ||||
|     const prompt = getPromptInfoById(value) | ||||
|     if (prompt?.is_system) { | ||||
|       setSelectedSystemPrompt(prompt.id) | ||||
|     } else { | ||||
|       setSelectedSystemPrompt(undefined) | ||||
|       setSelectedQuickPrompt(prompt!.content) | ||||
|     } | ||||
|   } | ||||
| 
 | ||||
|   return ( | ||||
|     <div> | ||||
|       <div> | ||||
|         <div className="flex flex-col"> | ||||
|           <div className="sticky top-0 z-[999] flex h-16 p-3  bg-gray-50 border-b  dark:bg-[#171717] dark:border-gray-600"> | ||||
|             <div className="flex gap-2 items-center"> | ||||
|               {pathname !== "/" && ( | ||||
|                 <div> | ||||
|                   <NavLink | ||||
|                     to="/" | ||||
|                     className="text-gray-500 items-center dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"> | ||||
|                     <ChevronLeft className="w-4 h-4" /> | ||||
|                   </NavLink> | ||||
|                 </div> | ||||
|               )} | ||||
|               <div> | ||||
|                 <button | ||||
|                   className="text-gray-500 dark:text-gray-400" | ||||
|                   onClick={() => setSidebarOpen(true)}> | ||||
|                   <PanelLeftIcon className="w-6 h-6" /> | ||||
|                 </button> | ||||
|               </div> | ||||
|               <div> | ||||
|                 <button | ||||
|                   onClick={clearChat} | ||||
|                   className="inline-flex  dark:bg-transparent bg-white items-center rounded-lg border  dark:border-gray-700 bg-transparent px-3 py-2.5 text-xs lg:text-sm font-medium leading-4 text-gray-800  dark:text-white disabled:opacity-50 ease-in-out transition-colors duration-200 hover:bg-gray-100 dark:hover:bg-gray-800 dark:hover:text-white"> | ||||
|                   <SquarePen className="h-5 w-5 " /> | ||||
|                   <span className=" truncate ml-3">{t("newChat")}</span> | ||||
|                 </button> | ||||
|               </div> | ||||
|               <span className="text-lg font-thin text-zinc-300 dark:text-zinc-600"> | ||||
|                 {"/"} | ||||
|               </span> | ||||
|               <div className="hidden lg:block"> | ||||
|                 <Select | ||||
|                   value={selectedModel} | ||||
|                   onChange={(e) => { | ||||
|                     setSelectedModel(e) | ||||
|                     localStorage.setItem("selectedModel", e) | ||||
|                   }} | ||||
|                   size="large" | ||||
|                   loading={isModelsLoading || isModelsFetching} | ||||
|                   filterOption={(input, option) => | ||||
|                     option.label.key | ||||
|                       .toLowerCase() | ||||
|                       .indexOf(input.toLowerCase()) >= 0 | ||||
|                   } | ||||
|                   showSearch | ||||
|                   placeholder={t("common:selectAModel")} | ||||
|                   className="w-64 " | ||||
|                   options={models?.map((model) => ({ | ||||
|                     label: ( | ||||
|                       <span | ||||
|                         key={model.model} | ||||
|                         className="flex flex-row gap-3 items-center"> | ||||
|                         <OllamaIcon className="w-5 h-5" /> | ||||
|                         {model.name} | ||||
|                       </span> | ||||
|                     ), | ||||
|                     value: model.model | ||||
|                   }))} | ||||
|                 /> | ||||
|               </div> | ||||
|               <div className="lg:hidden"> | ||||
|                 <ModelSelect /> | ||||
|               </div> | ||||
|               <span className="text-lg font-thin text-zinc-300 dark:text-zinc-600"> | ||||
|                 {"/"} | ||||
|               </span> | ||||
|               <div className="hidden lg:block"> | ||||
|                 <Select | ||||
|                   size="large" | ||||
|                   loading={isPromptLoading} | ||||
|                   showSearch | ||||
|                   placeholder={t("selectAPrompt")} | ||||
|                   className="w-60" | ||||
|                   allowClear | ||||
|                   onChange={handlePromptChange} | ||||
|                   value={selectedSystemPrompt} | ||||
|                   filterOption={(input, option) => | ||||
|                     //@ts-ignore
 | ||||
|                     option.label.key | ||||
|                       .toLowerCase() | ||||
|                       .indexOf(input.toLowerCase()) >= 0 | ||||
|                   } | ||||
|                   options={prompts?.map((prompt) => ({ | ||||
|                     label: ( | ||||
|                       <span | ||||
|                         key={prompt.title} | ||||
|                         className="flex flex-row gap-3 items-center"> | ||||
|                         {prompt.is_system ? ( | ||||
|                           <ComputerIcon className="w-4 h-4" /> | ||||
|                         ) : ( | ||||
|                           <ZapIcon className="w-4 h-4" /> | ||||
|                         )} | ||||
|                         {prompt.title} | ||||
|                       </span> | ||||
|                     ), | ||||
|                     value: prompt.id | ||||
|                   }))} | ||||
|                 /> | ||||
|               </div> | ||||
|               <div className="lg:hidden"> | ||||
|                 <PromptSelect /> | ||||
|               </div> | ||||
|               <SelectedKnowledge /> | ||||
|             </div> | ||||
|             <div className="flex flex-1 justify-end px-4"> | ||||
|               <div className="ml-4 flex items-center md:ml-6"> | ||||
|                 <div className="flex gap-4 items-center"> | ||||
|                   {!hideCurrentChatModelSettings && ( | ||||
|                     <Tooltip title={t("common:currentChatModelSettings")}> | ||||
|                       <button | ||||
|                         onClick={() => setOpenModelSettings(true)} | ||||
|                         className="!text-gray-500 dark:text-gray-300 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"> | ||||
|                         <BrainCog className="w-6 h-6" /> | ||||
|                       </button> | ||||
|                     </Tooltip> | ||||
|                   )} | ||||
|                   {pathname === "/" && | ||||
|                     messages.length > 0 && | ||||
|                     !streaming && | ||||
|                     shareModeEnabled && <ShareBtn messages={messages} />} | ||||
|                   <Tooltip title={t("githubRepository")}> | ||||
|                     <a | ||||
|                       href="https://github.com/n4ze3m/page-assist" | ||||
|                       target="_blank" | ||||
|                       className="!text-gray-500 hidden lg:block dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"> | ||||
|                       <GithubIcon className="w-6 h-6" /> | ||||
|                     </a> | ||||
|                   </Tooltip> | ||||
|                   <Tooltip title={t("settings")}> | ||||
|                     <NavLink | ||||
|                       to="/settings" | ||||
|                       className="!text-gray-500 dark:text-gray-400 hover:text-gray-600 dark:hover:text-gray-300 transition-colors"> | ||||
|                       <CogIcon className="w-6 h-6" /> | ||||
|                     </NavLink> | ||||
|                   </Tooltip> | ||||
|                 </div> | ||||
|               </div> | ||||
|             </div> | ||||
|           </div> | ||||
|           <main className="flex-1">{children}</main> | ||||
|         </div> | ||||
|     <> | ||||
|       <div className="flex flex-col min-h-screen"> | ||||
|         <Header | ||||
|           setSidebarOpen={setSidebarOpen} | ||||
|           setOpenModelSettings={setOpenModelSettings} | ||||
|         /> | ||||
|         <main className="flex-1">{children}</main> | ||||
|       </div> | ||||
| 
 | ||||
|       <Drawer | ||||
| @ -246,6 +40,6 @@ export default function OptionLayout({ | ||||
|         open={openModelSettings} | ||||
|         setOpen={setOpenModelSettings} | ||||
|       /> | ||||
|     </div> | ||||
|     </> | ||||
|   ) | ||||
| } | ||||
|  | ||||
							
								
								
									
										87
									
								
								src/hooks/useScrollAnchor.tsx
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										87
									
								
								src/hooks/useScrollAnchor.tsx
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,87 @@ | ||||
| import { useCallback, useEffect, useRef, useState } from "react" | ||||
| 
 | ||||
| export const useScrollAnchor = () => { | ||||
|   const messagesRef = useRef<HTMLDivElement>(null) | ||||
|   const scrollRef = useRef<HTMLDivElement>(null) | ||||
|   const visibilityRef = useRef<HTMLDivElement>(null) | ||||
| 
 | ||||
|   const [isAtBottom, setIsAtBottom] = useState(true) | ||||
|   const [isVisible, setIsVisible] = useState(false) | ||||
| 
 | ||||
|   const scrollToBottom = useCallback(() => { | ||||
|     if (messagesRef.current) { | ||||
|       messagesRef.current.scrollIntoView({ | ||||
|         block: "end", | ||||
|         behavior: "smooth" | ||||
|       }) | ||||
|     } | ||||
|   }, []) | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     if (messagesRef.current) { | ||||
|       if (isAtBottom && !isVisible) { | ||||
|         messagesRef.current.scrollIntoView({ | ||||
|           block: "end" | ||||
|         }) | ||||
|       } | ||||
|     } | ||||
|   }, [isAtBottom, isVisible]) | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     const { current } = scrollRef | ||||
| 
 | ||||
|     if (current) { | ||||
|       const handleScroll = (event: Event) => { | ||||
|         const target = event.target as HTMLDivElement | ||||
|         const offset = 25 | ||||
|         const isAtBottom = | ||||
|           target.scrollTop + target.clientHeight >= target.scrollHeight - offset | ||||
|         console.log(target.scrollTop, target.clientHeight, target.scrollHeight) | ||||
|         setIsAtBottom(isAtBottom) | ||||
|       } | ||||
| 
 | ||||
|       current.addEventListener("scroll", handleScroll, { | ||||
|         passive: true | ||||
|       }) | ||||
| 
 | ||||
|       return () => { | ||||
|         current.removeEventListener("scroll", handleScroll) | ||||
|       } | ||||
|     } | ||||
|   }, []) | ||||
| 
 | ||||
|   useEffect(() => { | ||||
|     if (visibilityRef.current) { | ||||
|       let observer = new IntersectionObserver( | ||||
|         (entries) => { | ||||
|           entries.forEach((entry) => { | ||||
|             console.log(entry.isIntersecting) | ||||
|             if (entry.isIntersecting) { | ||||
|               setIsVisible(true) | ||||
|             } else { | ||||
|               setIsVisible(false) | ||||
|             } | ||||
|           }) | ||||
|         }, | ||||
|         { | ||||
|           rootMargin: "0px 0px -100px 0px" | ||||
|         } | ||||
|       ) | ||||
| 
 | ||||
|       observer.observe(visibilityRef.current) | ||||
| 
 | ||||
|       return () => { | ||||
|         observer.disconnect() | ||||
|       } | ||||
|     } | ||||
|   }) | ||||
| 
 | ||||
|   return { | ||||
|     messagesRef, | ||||
|     scrollRef, | ||||
|     visibilityRef, | ||||
|     scrollToBottom, | ||||
|     isAtBottom, | ||||
|     isVisible | ||||
|   } | ||||
| } | ||||
| @ -2,10 +2,12 @@ import i18n from "i18next"; | ||||
| import { initReactI18next } from "react-i18next"; | ||||
| import { en } from "./lang/en"; | ||||
| import { pt } from "./lang/pt"; | ||||
| import { fr } from "./lang/fr"; | ||||
| import { ru } from "./lang/ru"; | ||||
| import { ml } from "./lang/ml"; | ||||
| import { zh } from "./lang/zh"; | ||||
| import { ja } from "./lang/ja"; | ||||
| import { it } from "./lang/it"; | ||||
| import LanguageDetector from 'i18next-browser-languagedetector'; | ||||
| 
 | ||||
| i18n | ||||
| @ -14,6 +16,8 @@ i18n | ||||
|     .init({ | ||||
|         resources: { | ||||
|             en: en, | ||||
|             fr: fr, | ||||
|             "it": it, | ||||
|             ml: ml, | ||||
|             "pt-BR": pt, | ||||
|             "zh-CN": zh, | ||||
|  | ||||
							
								
								
									
										15
									
								
								src/i18n/lang/fr.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/i18n/lang/fr.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| import option from "@/assets/locale/fr/option.json"; | ||||
| import playground from "@/assets/locale/fr/playground.json"; | ||||
| import common from "@/assets/locale/fr/common.json"; | ||||
| import sidepanel from "@/assets/locale/fr/sidepanel.json"; | ||||
| import settings from "@/assets/locale/fr/settings.json"; | ||||
| import knowledge from "@/assets/locale/fr/knowledge.json"; | ||||
| 
 | ||||
| export const fr = { | ||||
|     option, | ||||
|     playground, | ||||
|     common, | ||||
|     sidepanel, | ||||
|     settings, | ||||
|     knowledge | ||||
| } | ||||
							
								
								
									
										15
									
								
								src/i18n/lang/it.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										15
									
								
								src/i18n/lang/it.ts
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,15 @@ | ||||
| import option from "@/assets/locale/it/option.json"; | ||||
| import playground from "@/assets/locale/it/playground.json"; | ||||
| import common from "@/assets/locale/it/common.json"; | ||||
| import sidepanel from "@/assets/locale/it/sidepanel.json"; | ||||
| import settings from "@/assets/locale/it/settings.json"; | ||||
| import knowledge from "@/assets/locale/it/knowledge.json"; | ||||
| 
 | ||||
| export const it = { | ||||
|     option, | ||||
|     playground, | ||||
|     common, | ||||
|     sidepanel, | ||||
|     settings, | ||||
|     knowledge | ||||
| } | ||||
| @ -4,6 +4,14 @@ export const supportLanguage = [ | ||||
|         label: "English", | ||||
|         value: "en" | ||||
|     }, | ||||
|     { | ||||
|         label: "Français", | ||||
|         value: "fr" | ||||
|     }, | ||||
|     { | ||||
|         label: "Italiano", | ||||
|         value: "it" | ||||
|     }, | ||||
|     { | ||||
|         label: "Russian", | ||||
|         value: "ru" | ||||
|  | ||||
| @ -2,7 +2,8 @@ import { getKnowledgeById, updateKnowledgeStatus } from "@/db/knowledge" | ||||
| import { PageAssistPDFUrlLoader } from "@/loader/pdf-url" | ||||
| import { | ||||
|   defaultEmbeddingChunkOverlap, | ||||
|   defaultEmbeddingChunkSize | ||||
|   defaultEmbeddingChunkSize, | ||||
|   getOllamaURL | ||||
| } from "@/services/ollama" | ||||
| import { OllamaEmbeddings } from "@langchain/community/embeddings/ollama" | ||||
| import { RecursiveCharacterTextSplitter } from "langchain/text_splitter" | ||||
| @ -10,22 +11,14 @@ import { PageAssistVectorStore } from "./PageAssistVectorStore" | ||||
| import { PageAssisCSVUrlLoader } from "@/loader/csv" | ||||
| import { PageAssisTXTUrlLoader } from "@/loader/txt" | ||||
| import { PageAssistDocxLoader } from "@/loader/docx" | ||||
| import { cleanUrl } from "./clean-url" | ||||
| 
 | ||||
| const readAsArrayBuffer = (file: File): Promise<ArrayBuffer> => { | ||||
|   return new Promise((resolve, reject) => { | ||||
|     const reader = new FileReader() | ||||
|     reader.onload = () => { | ||||
|       resolve(reader.result as ArrayBuffer) | ||||
|     } | ||||
|     reader.onerror = reject | ||||
|     reader.readAsArrayBuffer(file) | ||||
|   }) | ||||
| } | ||||
| 
 | ||||
| export const processKnowledge = async (msg: any, id: string): Promise<void> => { | ||||
|   console.log(`Processing knowledge with id: ${id}`) | ||||
|   try { | ||||
|     const knowledge = await getKnowledgeById(id) | ||||
|     const ollamaUrl = await getOllamaURL() | ||||
| 
 | ||||
|     if (!knowledge) { | ||||
|       console.error(`Knowledge with id ${id} not found`) | ||||
| @ -35,6 +28,7 @@ export const processKnowledge = async (msg: any, id: string): Promise<void> => { | ||||
|     await updateKnowledgeStatus(id, "processing") | ||||
| 
 | ||||
|     const ollamaEmbedding = new OllamaEmbeddings({ | ||||
|       baseUrl: cleanUrl(ollamaUrl), | ||||
|       model: knowledge.embedding_model | ||||
|     }) | ||||
|     const chunkSize = await defaultEmbeddingChunkSize() | ||||
|  | ||||
							
								
								
									
										11
									
								
								src/public/_locales/fr/messages.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/public/_locales/fr/messages.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| { | ||||
|     "extName": { | ||||
|         "message": "Page Assist - Une interface Web pour les modèles d'IA locaux" | ||||
|     }, | ||||
|     "extDescription": { | ||||
|         "message": "Utilisez vos modèles d'IA locaux pour vous aider dans votre navigation web." | ||||
|     }, | ||||
|     "openSidePanelToChat": { | ||||
|         "message": "Ouvrir Copilot pour discuter" | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								src/public/_locales/it/messages.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/public/_locales/it/messages.json
									
									
									
									
									
										Normal file
									
								
							| @ -0,0 +1,11 @@ | ||||
| { | ||||
|     "extName": { | ||||
|         "message": "Page Assist - Un'interfaccia web per modelli AI locali" | ||||
|     }, | ||||
|     "extDescription": { | ||||
|         "message": "Usa i tuoi modelli AI in esecuzione locale per assisterti nella navigazione web." | ||||
|     }, | ||||
|     "openSidePanelToChat": { | ||||
|         "message": "Apri Copilot per chattare" | ||||
|     } | ||||
| } | ||||
| @ -48,7 +48,7 @@ export default defineConfig({ | ||||
|   outDir: "build", | ||||
| 
 | ||||
|   manifest: { | ||||
|     version: "1.1.10", | ||||
|     version: "1.1.11", | ||||
|     name: | ||||
|       process.env.TARGET === "firefox" | ||||
|         ? "Page Assist - A Web UI for Local AI Models" | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user