commit
914e358ee8
@ -193,7 +193,9 @@
|
||||
},
|
||||
"confirm": {
|
||||
"delete": "Are you sure you want to delete this share? This action cannot be undone."
|
||||
}
|
||||
},
|
||||
"label": "Manage Page Share",
|
||||
"description": "Enable or disable the page share feature. By default, the page share feature is enabled."
|
||||
},
|
||||
"notification": {
|
||||
"pageShareSuccess": "Page Share URL updated successfully",
|
||||
|
@ -196,7 +196,9 @@
|
||||
},
|
||||
"confirm": {
|
||||
"delete": "本当にこの共有を削除しますか?この操作は元に戻せません。"
|
||||
}
|
||||
},
|
||||
"label": "ページ共有を管理する",
|
||||
"description": "ページ共有機能を有効または無効にします。デフォルトでは、ページ共有機能は有効になっています。"
|
||||
},
|
||||
"notification": {
|
||||
"pageShareSuccess": "ページ共有URLが正常に更新されました",
|
||||
|
@ -196,7 +196,9 @@
|
||||
},
|
||||
"confirm": {
|
||||
"delete": "ഈ പങ്കിടല് ഇല്ലാതാക്കണമെന്ന് തീർച്ചയാണോ? ഈ പ്രവർത്തനം പിന്നീട് പിൻവലിക്കാനാകില്ല."
|
||||
}
|
||||
},
|
||||
"label": "പേജ് ഷെയർ നിയന്ത്രിക്കുക",
|
||||
"description": "പേജ് ഷെയർ സവിശേഷത സജീവമാക്കുകയോ അക്ഷമമാക്കുകയോ ചെയ്യുക. സ്ഥിരംമായി, പേജ് ഷെയർ സവിശേഷത സജീവമാക്കപ്പെടുന്നു."
|
||||
},
|
||||
"notification": {
|
||||
"pageShareSuccess": "പേജ് പങ്കിടാനുള്ള URL വിജയകരമായി അപ്ഡേറ്റ് ചെയ്തു",
|
||||
|
54
src/assets/locale/ru/common.json
Normal file
54
src/assets/locale/ru/common.json
Normal file
@ -0,0 +1,54 @@
|
||||
{
|
||||
"pageAssist": "Помощник страницы",
|
||||
"selectAModel": "Выберите модель",
|
||||
"save": "Сохранить",
|
||||
"saved": "Сохранено",
|
||||
"cancel": "Отмена",
|
||||
"retry": "Повторить",
|
||||
"share": {
|
||||
"tooltip": {
|
||||
"share": "Поделиться"
|
||||
},
|
||||
"modal": {
|
||||
"title": "Поделиться ссылкой на чат"
|
||||
},
|
||||
"form": {
|
||||
"defaultValue": {
|
||||
"name": "Аноним",
|
||||
"title": "Безымянный чат"
|
||||
},
|
||||
"title": {
|
||||
"label": "Название чата",
|
||||
"placeholder": "Введите название чата",
|
||||
"required": "Название чата обязательно"
|
||||
},
|
||||
"name": {
|
||||
"label": "Ваше имя",
|
||||
"placeholder": "Введите ваше имя",
|
||||
"required": "Ваше имя обязательно"
|
||||
},
|
||||
"btn": {
|
||||
"save": "Создать ссылку",
|
||||
"saving": "Создание ссылки..."
|
||||
}
|
||||
},
|
||||
"notification": {
|
||||
"successGenerate": "Ссылка скопирована в буфер обмена",
|
||||
"failGenerate": "Не удалось создать ссылку"
|
||||
}
|
||||
},
|
||||
"copyToClipboard": "Копировать в буфер обмена",
|
||||
"webSearch": "Поиск в интернете",
|
||||
"regenerate": "Пересоздать",
|
||||
"edit": "Редактировать",
|
||||
"saveAndSubmit": "Сохранить и отправить",
|
||||
"editMessage": {
|
||||
"placeholder": "Введите сообщение..."
|
||||
},
|
||||
"submit": "Отправить",
|
||||
"noData": "Нет данных",
|
||||
"noHistory": "Нет истории чата",
|
||||
"chatWithCurrentPage": "Чат с текущей страницей",
|
||||
"beta": "Бета",
|
||||
"tts": "Прочитать вслух"
|
||||
}
|
42
src/assets/locale/ru/knowledge.json
Normal file
42
src/assets/locale/ru/knowledge.json
Normal file
@ -0,0 +1,42 @@
|
||||
{
|
||||
"addBtn": "Добавить новое знание",
|
||||
"columns": {
|
||||
"title": "Название",
|
||||
"status": "Статус",
|
||||
"embeddings": "Модель вложения",
|
||||
"createdAt": "Создано",
|
||||
"action": "Действия"
|
||||
},
|
||||
"expandedColumns": {
|
||||
"name": "Имя"
|
||||
},
|
||||
"tooltip": {
|
||||
"delete": "Удалить"
|
||||
},
|
||||
"confirm": {
|
||||
"delete": "Вы уверены, что хотите удалить это знание?"
|
||||
},
|
||||
"deleteSuccess": "Знание успешно удалено",
|
||||
"status": {
|
||||
"pending": "Ожидание",
|
||||
"finished": "Завершено",
|
||||
"processing": "Обработка"
|
||||
},
|
||||
"addKnowledge": "Добавить знание",
|
||||
"form": {
|
||||
"title": {
|
||||
"label": "Название знания",
|
||||
"placeholder": "Введите название знания",
|
||||
"required": "Название знания обязательно"
|
||||
},
|
||||
"uploadFile": {
|
||||
"label": "Загрузить файл",
|
||||
"uploadText": "Перетащите файл сюда или нажмите, чтобы загрузить",
|
||||
"uploadHint": "Поддерживаемые типы файлов: .pdf, .csv, .txt, .md",
|
||||
"required": "Файл обязателен"
|
||||
},
|
||||
"submit": "Отправить",
|
||||
"success": "Знание успешно добавлено"
|
||||
},
|
||||
"noEmbeddingModel": "Пожалуйста, сначала добавьте модель вложения на странице настроек Ollama"
|
||||
}
|
12
src/assets/locale/ru/option.json
Normal file
12
src/assets/locale/ru/option.json
Normal file
@ -0,0 +1,12 @@
|
||||
{
|
||||
"newChat": "Новый чат",
|
||||
"selectAPrompt": "Выберите подсказку",
|
||||
"githubRepository": "Репозиторий GitHub",
|
||||
"settings": "Настройки",
|
||||
"sidebarTitle": "История чата",
|
||||
"error": "Ошибка",
|
||||
"somethingWentWrong": "Что-то пошло не так",
|
||||
"validationSelectModel": "Пожалуйста, выберите модель, чтобы продолжить",
|
||||
"deleteHistoryConfirmation": "Вы уверены, что хотите удалить эту историю?",
|
||||
"editHistoryTitle": "Введите новое название"
|
||||
}
|
28
src/assets/locale/ru/playground.json
Normal file
28
src/assets/locale/ru/playground.json
Normal file
@ -0,0 +1,28 @@
|
||||
{
|
||||
"ollamaState": {
|
||||
"searching": "Поиск вашего Ollama 🦙",
|
||||
"running": "Ollama работает 🦙",
|
||||
"notRunning": "Не удалось подключиться к Ollama 🦙"
|
||||
},
|
||||
"formError": {
|
||||
"noModel": "Пожалуйста, выберите модель",
|
||||
"noEmbeddingModel": "Пожалуйста, установите модель вложения на странице Настройки > Ollama"
|
||||
},
|
||||
"form": {
|
||||
"textarea": {
|
||||
"placeholder": "Введите сообщение..."
|
||||
},
|
||||
"webSearch": {
|
||||
"on": "Вкл",
|
||||
"off": "Выкл"
|
||||
}
|
||||
},
|
||||
"tooltip": {
|
||||
"searchInternet": "Поиск в Интернете",
|
||||
"speechToText": "Речь в текст",
|
||||
"uploadImage": "Загрузить изображение",
|
||||
"stopStreaming": "Остановить поток",
|
||||
"knowledge": "Знание"
|
||||
},
|
||||
"sendWhenEnter": "Отправить при нажатии клавиши Enter"
|
||||
}
|
269
src/assets/locale/ru/settings.json
Normal file
269
src/assets/locale/ru/settings.json
Normal file
@ -0,0 +1,269 @@
|
||||
{
|
||||
"generalSettings": {
|
||||
"title": "Общие настройки",
|
||||
"settings": {
|
||||
"heading": "Настройки веб-интерфейса",
|
||||
"speechRecognitionLang": {
|
||||
"label": "Язык распознавания речи",
|
||||
"placeholder": "Выберите язык"
|
||||
},
|
||||
"language": {
|
||||
"label": "Язык",
|
||||
"placeholder": "Выберите язык"
|
||||
},
|
||||
"darkMode": {
|
||||
"label": "Сменить тему",
|
||||
"options": {
|
||||
"light": "Светлая",
|
||||
"dark": "Темная"
|
||||
}
|
||||
}
|
||||
},
|
||||
"webSearch": {
|
||||
"heading": "Управление веб-поиском",
|
||||
"searchMode": {
|
||||
"label": "Выполнить простой интернет-поиск"
|
||||
},
|
||||
"provider": {
|
||||
"label": "Поисковый движок",
|
||||
"placeholder": "Выберите поисковый движок"
|
||||
},
|
||||
"totalSearchResults": {
|
||||
"label": "Общее количество результатов поиска",
|
||||
"placeholder": "Введите общее количество результатов поиска"
|
||||
}
|
||||
},
|
||||
"system": {
|
||||
"heading": "Настройки системы",
|
||||
"deleteChatHistory": {
|
||||
"label": "Удалить историю чата",
|
||||
"button": "Удалить",
|
||||
"confirm": "Вы уверены, что хотите удалить историю чата? Это действие нельзя отменить."
|
||||
},
|
||||
"export": {
|
||||
"label": "Экспорт истории чата, настроек и подсказок",
|
||||
"button": "Экспорт данных",
|
||||
"success": "Экспорт успешен"
|
||||
},
|
||||
"import": {
|
||||
"label": "Импорт истории чата, настроек и подсказок",
|
||||
"button": "Импорт данных",
|
||||
"success": "Импорт успешен",
|
||||
"error": "Ошибка импорта"
|
||||
}
|
||||
},
|
||||
"tts": {
|
||||
"heading": "Настройки текст в речь",
|
||||
"ttsEnabled": {
|
||||
"label": "Включить текст в речь"
|
||||
},
|
||||
"ttsProvider": {
|
||||
"label": "Поставщик текста в речь",
|
||||
"placeholder": "Выберите поставщика"
|
||||
},
|
||||
"ttsVoice": {
|
||||
"label": "Голос текста в речь",
|
||||
"placeholder": "Выберите голос"
|
||||
},
|
||||
"ssmlEnabled": {
|
||||
"label": "Включить SSML (язык разметки синтеза речи)"
|
||||
}
|
||||
}
|
||||
},
|
||||
"manageModels": {
|
||||
"title": "Управление моделями",
|
||||
"addBtn": "Добавить новую модель",
|
||||
"columns": {
|
||||
"name": "Название",
|
||||
"digest": "Дайджест",
|
||||
"modifiedAt": "Изменено",
|
||||
"size": "Размер",
|
||||
"actions": "Действия"
|
||||
},
|
||||
"expandedColumns": {
|
||||
"parentModel": "Родительская модель",
|
||||
"format": "Формат",
|
||||
"family": "Семейство",
|
||||
"parameterSize": "Размер параметров",
|
||||
"quantizationLevel": "Уровень квантования"
|
||||
},
|
||||
"tooltip": {
|
||||
"delete": "Удалить модель",
|
||||
"repull": "Переполучить модель"
|
||||
},
|
||||
"confirm": {
|
||||
"delete": "Вы уверены, что хотите удалить эту модель?",
|
||||
"repull": "Вы уверены, что хотите переполучить эту модель?"
|
||||
},
|
||||
"modal": {
|
||||
"title": "Добавить новую модель",
|
||||
"placeholder": "Введите название модели",
|
||||
"pull": "Получить модель"
|
||||
},
|
||||
"notification": {
|
||||
"pullModel": "Получение модели",
|
||||
"pullModelDescription": "Получение модели {{modelName}}. Для получения дополнительной информации проверьте значок расширения.",
|
||||
"success": "Успех",
|
||||
"error": "Ошибка",
|
||||
"successDescription": "Модель успешно получена",
|
||||
"successDeleteDescription": "Модель успешно удалена",
|
||||
"someError": "Что-то пошло не так. Пожалуйста, попробуйте позже"
|
||||
}
|
||||
},
|
||||
"managePrompts": {
|
||||
"title": "Управление подсказками",
|
||||
"addBtn": "Добавить новую подсказку",
|
||||
"option1": "Обычная",
|
||||
"option2": "RAG",
|
||||
"questionPrompt": "Вопросная подсказка",
|
||||
"columns": {
|
||||
"title": "Название",
|
||||
"prompt": "Подсказка",
|
||||
"type": "Тип подсказки",
|
||||
"actions": "Действия"
|
||||
},
|
||||
"systemPrompt": "Системная подсказка",
|
||||
"quickPrompt": "Быстрая подсказка",
|
||||
"tooltip": {
|
||||
"delete": "Удалить подсказку",
|
||||
"edit": "Редактировать подсказку"
|
||||
},
|
||||
"confirm": {
|
||||
"delete": "Вы уверены, что хотите удалить эту подсказку? Это действие нельзя отменить."
|
||||
},
|
||||
"modal": {
|
||||
"addTitle": "Добавить новую подсказку",
|
||||
"editTitle": "Редактировать подсказку"
|
||||
},
|
||||
"form": {
|
||||
"title": {
|
||||
"label": "Название",
|
||||
"placeholder": "Моя замечательная подсказка",
|
||||
"required": "Пожалуйста, введите название"
|
||||
},
|
||||
"prompt": {
|
||||
"label": "Подсказка",
|
||||
"placeholder": "Введите подсказку",
|
||||
"required": "Пожалуйста, введите подсказку",
|
||||
"help": "Вы можете использовать {key} в качестве переменной в своей подсказке."
|
||||
},
|
||||
"isSystem": {
|
||||
"label": "Это системная подсказка"
|
||||
},
|
||||
"btnSave": {
|
||||
"saving": "Добавление подсказки...",
|
||||
"save": "Добавить подсказку"
|
||||
},
|
||||
"btnEdit": {
|
||||
"saving": "Обновление подсказки...",
|
||||
"save": "Обновить подсказку"
|
||||
}
|
||||
},
|
||||
"notification": {
|
||||
"addSuccess": "Подсказка добавлена",
|
||||
"addSuccessDesc": "Подсказка успешно добавлена",
|
||||
"error": "Ошибка",
|
||||
"someError": "Что-то пошло не так. Пожалуйста, попробуйте позже",
|
||||
"updatedSuccess": "Подсказка обновлена",
|
||||
"updatedSuccessDesc": "Подсказка успешно обновлена",
|
||||
"deletedSuccess": "Подсказка удалена",
|
||||
"deletedSuccessDesc": "Подсказка успешно удалена"
|
||||
}
|
||||
},
|
||||
"manageShare": {
|
||||
"title": "Управление обменом",
|
||||
"heading": "Настройка URL обмена страницей",
|
||||
"form": {
|
||||
"url": {
|
||||
"label": "URL обмена страницей",
|
||||
"placeholder": "Введите URL обмена страницей",
|
||||
"required": "Пожалуйста, введите ваш URL обмена страницей!",
|
||||
"help": "По соображениям конфиденциальности вы можете самостоятельно разместить страницу обмена и указать здесь URL. <anchor>Узнать больше</anchor>."
|
||||
}
|
||||
},
|
||||
"webshare": {
|
||||
"heading": "Веб-обмен",
|
||||
"columns": {
|
||||
"title": "Название",
|
||||
"url": "URL",
|
||||
"actions": "Действия"
|
||||
},
|
||||
"tooltip": {
|
||||
"delete": "Удалить обмен"
|
||||
},
|
||||
"confirm": {
|
||||
"delete": "Вы уверены, что хотите удалить этот обмен? Это действие нельзя отменить."
|
||||
},
|
||||
"label": "Управление общим доступом к странице",
|
||||
"description": "Включите или отключите функцию общего доступа к странице. По умолчанию функция общего доступа к странице включена."
|
||||
},
|
||||
"notification": {
|
||||
"pageShareSuccess": "URL обмена страницей успешно обновлен",
|
||||
"someError": "Что-то пошло не так. Пожалуйста, попробуйте позже",
|
||||
"webShareDeleteSuccess": "Веб-обмен успешно удален"
|
||||
}
|
||||
},
|
||||
"ollamaSettings": {
|
||||
"title": "Настройки Ollama",
|
||||
"heading": "Настройка Ollama",
|
||||
"settings": {
|
||||
"ollamaUrl": {
|
||||
"label": "URL Ollama",
|
||||
"placeholder": "Введите URL Ollama"
|
||||
},
|
||||
"ragSettings": {
|
||||
"label": "Настройки RAG",
|
||||
"model": {
|
||||
"label": "Модель вложения",
|
||||
"required": "Пожалуйста, выберите модель",
|
||||
"help": "Настоятельно рекомендуется использовать модели вложения, например, `nomic-embed-text`.",
|
||||
"placeholder": "Выберите модель"
|
||||
},
|
||||
"chunkSize": {
|
||||
"label": "Размер фрагмента",
|
||||
"placeholder": "Введите размер фрагмента",
|
||||
"required": "Пожалуйста, введите размер фрагмента"
|
||||
},
|
||||
"chunkOverlap": {
|
||||
"label": "Перекрытие фрагментов",
|
||||
"placeholder": "Введите перекрытие фрагментов",
|
||||
"required": "Пожалуйста, введите перекрытие фрагментов"
|
||||
}
|
||||
},
|
||||
"prompt": {
|
||||
"label": "Настройка системной подсказки RAG",
|
||||
"option1": "Обычная",
|
||||
"option2": "Веб",
|
||||
"alert": "Настройка системной подсказки здесь устарела. Используйте раздел Управление подсказками для добавления или редактирования подсказок. Этот раздел будет удален в будущем выпуске",
|
||||
"systemPrompt": "Системная подсказка",
|
||||
"systemPromptPlaceholder": "Введите системную подсказку",
|
||||
"webSearchPrompt": "Подсказка для веб-поиска",
|
||||
"webSearchPromptHelp": "Не удаляйте `{search_results}` из подсказки.",
|
||||
"webSearchPromptError": "Пожалуйста, введите подсказку для веб-поиска",
|
||||
"webSearchPromptPlaceholder": "Введите подсказку для веб-поиска",
|
||||
"webSearchFollowUpPrompt": "Последующая подсказка для веб-поиска",
|
||||
"webSearchFollowUpPromptHelp": "Не удаляйте `{chat_history}` и `{question}` из подсказки.",
|
||||
"webSearchFollowUpPromptError": "Введите подсказку для последующего веб-поиска!",
|
||||
"webSearchFollowUpPromptPlaceholder": "Ваша подсказка для последующего веб-поиска"
|
||||
}
|
||||
}
|
||||
},
|
||||
"manageSearch": {
|
||||
"title": "Управление веб-поиском",
|
||||
"heading": "Настройка веб-поиска"
|
||||
},
|
||||
"about": {
|
||||
"title": "О программе",
|
||||
"heading": "О программе",
|
||||
"chromeVersion": "Версия Page Assist",
|
||||
"ollamaVersion": "Версия Ollama",
|
||||
"support": "Вы можете поддержать проект Page Assist, сделав пожертвование или спонсорирование через следующие платформы:",
|
||||
"koFi": "Поддержать на Ko-fi",
|
||||
"githubSponsor": "Стать спонсором на GitHub",
|
||||
"githubRepo": "Репозиторий GitHub"
|
||||
},
|
||||
"manageKnowledge": {
|
||||
"title": "Управление знаниями",
|
||||
"heading": "Настройка базы знаний"
|
||||
}
|
||||
}
|
7
src/assets/locale/ru/sidepanel.json
Normal file
7
src/assets/locale/ru/sidepanel.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"tooltip": {
|
||||
"embed": "Внедрение страницы может занять несколько минут. Пожалуйста, подождите...",
|
||||
"clear": "Очистить историю чата",
|
||||
"history": "История чата"
|
||||
}
|
||||
}
|
@ -197,7 +197,9 @@
|
||||
},
|
||||
"confirm": {
|
||||
"delete": "您确定要删除此对话共享吗?这个操作不能撤销。"
|
||||
}
|
||||
},
|
||||
"label": "管理页面分享",
|
||||
"description": "启用或禁用页面分享功能。默认情况下,页面分享功能已启用。"
|
||||
},
|
||||
"notification": {
|
||||
"pageShareSuccess": "对话共享服务 URL 已成功更新",
|
||||
|
BIN
src/assets/onest.ttf
Normal file
BIN
src/assets/onest.ttf
Normal file
Binary file not shown.
@ -1,9 +1,19 @@
|
||||
@font-face {
|
||||
font-family: "font";
|
||||
src: url("font.ttf") format("truetype");
|
||||
font-family: "Inter";
|
||||
src: url("inter.ttf") format("truetype");
|
||||
}
|
||||
* {
|
||||
font-family: "font" !important;
|
||||
|
||||
@font-face {
|
||||
font-family: "Onest";
|
||||
src: url("onest.ttf") format("truetype");
|
||||
}
|
||||
|
||||
.inter {
|
||||
font-family: "Inter", sans-serif !important;
|
||||
}
|
||||
|
||||
.onest {
|
||||
font-family: "Onest", sans-serif !important;
|
||||
}
|
||||
|
||||
@tailwind base;
|
||||
@ -47,7 +57,7 @@
|
||||
@keyframes animatedgradient {
|
||||
0% {
|
||||
background-position: 0% 50%;
|
||||
}
|
||||
}
|
||||
50% {
|
||||
background-position: 100% 50%;
|
||||
}
|
||||
@ -62,6 +72,6 @@
|
||||
|
||||
/* Hide scrollbar for IE, Edge and Firefox */
|
||||
.no-scrollbar {
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
-ms-overflow-style: none; /* IE and Edge */
|
||||
scrollbar-width: none; /* Firefox */
|
||||
}
|
||||
|
@ -20,6 +20,7 @@ import { ShareBtn } from "~/components/Common/ShareBtn"
|
||||
import { useTranslation } from "react-i18next"
|
||||
import { OllamaIcon } from "../Icons/Ollama"
|
||||
import { SelectedKnowledge } from "../Option/Knowledge/SelectedKnwledge"
|
||||
import { useStorage } from "@plasmohq/storage/hook"
|
||||
|
||||
export default function OptionLayout({
|
||||
children
|
||||
@ -28,6 +29,7 @@ export default function OptionLayout({
|
||||
}) {
|
||||
const [sidebarOpen, setSidebarOpen] = useState(false)
|
||||
const { t } = useTranslation(["option", "common"])
|
||||
const [shareModeEnabled] = useStorage("shareMode", true)
|
||||
|
||||
const {
|
||||
selectedModel,
|
||||
@ -107,7 +109,7 @@ export default function OptionLayout({
|
||||
<div>
|
||||
<Select
|
||||
value={selectedModel}
|
||||
onChange={(e) => {
|
||||
onChange={(e) => {
|
||||
setSelectedModel(e)
|
||||
localStorage.setItem("selectedModel", e)
|
||||
}}
|
||||
@ -175,9 +177,10 @@ export default function OptionLayout({
|
||||
<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">
|
||||
{pathname === "/" && messages.length > 0 && !streaming && (
|
||||
<ShareBtn messages={messages} />
|
||||
)}
|
||||
{pathname === "/" &&
|
||||
messages.length > 0 &&
|
||||
!streaming &&
|
||||
shareModeEnabled && <ShareBtn messages={messages} />}
|
||||
<Tooltip title={t("githubRepository")}>
|
||||
<a
|
||||
href="https://github.com/n4ze3m/page-assist"
|
||||
|
@ -1,15 +1,17 @@
|
||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
||||
import { Form, Input, Skeleton, Table, Tooltip, message } from "antd"
|
||||
import { Form, Input, Skeleton, Switch, Table, Tooltip, message } from "antd"
|
||||
import { Trash2 } from "lucide-react"
|
||||
import { Trans, useTranslation } from "react-i18next"
|
||||
import { SaveButton } from "~/components/Common/SaveButton"
|
||||
import { deleteWebshare, getAllWebshares, getUserId } from "@/db"
|
||||
import { getPageShareUrl, setPageShareUrl } from "~/services/ollama"
|
||||
import { verifyPageShareURL } from "~/utils/verify-page-share"
|
||||
import { useStorage } from "@plasmohq/storage/hook"
|
||||
|
||||
export const OptionShareBody = () => {
|
||||
const queryClient = useQueryClient()
|
||||
const { t } = useTranslation(["settings"])
|
||||
const [shareModeEnabled, setShareModelEnabled] = useStorage("shareMode", true)
|
||||
|
||||
const { status, data } = useQuery({
|
||||
queryKey: ["fetchShareInfo"],
|
||||
@ -132,6 +134,20 @@ export const OptionShareBody = () => {
|
||||
</div>
|
||||
</Form.Item>
|
||||
</Form>
|
||||
<div className="space-y-2 flex mb-4 flex-row items-center justify-between rounded-lg dark:border-gray-600 ">
|
||||
<div className="space-y-0.5">
|
||||
<label className="text-sm font-semibold leading-5 text-gray-900 dark:text-white">
|
||||
{t("manageShare.webshare.label")}
|
||||
</label>
|
||||
<p className="text-sm font-normal leading-5 text-gray-500 dark:text-gray-400">
|
||||
{t("manageShare.webshare.description")}
|
||||
</p>
|
||||
</div>
|
||||
<Switch
|
||||
checked={shareModeEnabled}
|
||||
onChange={setShareModelEnabled}
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
<div>
|
||||
<div>
|
||||
|
@ -11,13 +11,16 @@ import { PageAssistProvider } from "@/components/Common/PageAssistProvider"
|
||||
|
||||
function IndexOption() {
|
||||
const { mode } = useDarkMode()
|
||||
const { t } = useTranslation()
|
||||
const { t, i18n } = useTranslation()
|
||||
return (
|
||||
<MemoryRouter>
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
algorithm:
|
||||
mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm
|
||||
mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm,
|
||||
token: {
|
||||
fontFamily: i18n.language === "ru" ? "Onest" : "Inter"
|
||||
}
|
||||
}}
|
||||
renderEmpty={() => (
|
||||
<Empty
|
||||
|
@ -11,14 +11,17 @@ import { PageAssistProvider } from "@/components/Common/PageAssistProvider"
|
||||
|
||||
function IndexSidepanel() {
|
||||
const { mode } = useDarkMode()
|
||||
const { t } = useTranslation()
|
||||
const { t, i18n } = useTranslation()
|
||||
|
||||
return (
|
||||
<MemoryRouter>
|
||||
<ConfigProvider
|
||||
theme={{
|
||||
algorithm:
|
||||
mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm
|
||||
mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm,
|
||||
token: {
|
||||
fontFamily: i18n.language === "ru" ? "Onest" : "Inter"
|
||||
}
|
||||
}}
|
||||
renderEmpty={() => (
|
||||
<Empty
|
||||
|
@ -1,6 +1,7 @@
|
||||
import i18n from "i18next";
|
||||
import { initReactI18next } from "react-i18next";
|
||||
import { en } from "./lang/en";
|
||||
import { ru } from "./lang/ru";
|
||||
import { ml } from "./lang/ml";
|
||||
import { zh } from "./lang/zh";
|
||||
import { ja } from "./lang/ja";
|
||||
@ -14,6 +15,8 @@ i18n
|
||||
en: en,
|
||||
ml: ml,
|
||||
"zh-CN": zh,
|
||||
ru: ru,
|
||||
"ru-RU": ru,
|
||||
zh: zh,
|
||||
ja: ja,
|
||||
"ja-JP": ja
|
||||
|
15
src/i18n/lang/ru.ts
Normal file
15
src/i18n/lang/ru.ts
Normal file
@ -0,0 +1,15 @@
|
||||
import option from "@/assets/locale/ru/option.json";
|
||||
import playground from "@/assets/locale/ru/playground.json";
|
||||
import common from "@/assets/locale/ru/common.json";
|
||||
import sidepanel from "@/assets/locale/ru/sidepanel.json";
|
||||
import settings from "@/assets/locale/ru/settings.json";
|
||||
import knowledge from "@/assets/locale/ru/knowledge.json";
|
||||
|
||||
export const ru = {
|
||||
option,
|
||||
playground,
|
||||
common,
|
||||
sidepanel,
|
||||
settings,
|
||||
knowledge
|
||||
}
|
@ -4,6 +4,10 @@ export const supportLanguage = [
|
||||
label: "English",
|
||||
value: "en"
|
||||
},
|
||||
{
|
||||
label: "Russian",
|
||||
value: "ru"
|
||||
},
|
||||
{
|
||||
label: "മലയാളം",
|
||||
value: "ml"
|
||||
|
11
src/public/_locales/ru/messages.json
Normal file
11
src/public/_locales/ru/messages.json
Normal file
@ -0,0 +1,11 @@
|
||||
{
|
||||
"extName": {
|
||||
"message": "Page Assist - Веб-интерфейс для локальных моделей искусственного интеллекта"
|
||||
},
|
||||
"extDescription": {
|
||||
"message": "Используйте запущенные локально модели искусственного интеллекта для помощи в веб-просмотре."
|
||||
},
|
||||
"openSidePanelToChat": {
|
||||
"message": "Открыть Copilot для чата"
|
||||
}
|
||||
}
|
@ -10,12 +10,17 @@ import { OptionSettings } from "./option-settings"
|
||||
import { OptionShare } from "./option-settings-share"
|
||||
import { OptionKnowledgeBase } from "./option-settings-knowledge"
|
||||
import { OptionAbout } from "./option-settings-about"
|
||||
import { useTranslation } from "react-i18next"
|
||||
|
||||
export const OptionRouting = () => {
|
||||
const { mode } = useDarkMode()
|
||||
const { i18n } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className={mode === "dark" ? "dark" : "light"}>
|
||||
<div
|
||||
className={`${mode === "dark" ? "dark" : "light"} ${
|
||||
i18n.language === "ru" ? "onest" : "inter"
|
||||
}`}>
|
||||
<Routes>
|
||||
<Route path="/" element={<OptionIndex />} />
|
||||
<Route path="/settings" element={<OptionSettings />} />
|
||||
@ -32,9 +37,13 @@ export const OptionRouting = () => {
|
||||
|
||||
export const SidepanelRouting = () => {
|
||||
const { mode } = useDarkMode()
|
||||
const { i18n } = useTranslation()
|
||||
|
||||
return (
|
||||
<div className={mode === "dark" ? "dark" : "light"}>
|
||||
<div
|
||||
className={`${mode === "dark" ? "dark" : "light"} ${
|
||||
i18n.language === "ru" ? "onest" : "inter"
|
||||
}`}>
|
||||
<Routes>
|
||||
<Route path="/" element={<SidepanelChat />} />
|
||||
<Route path="/settings" element={<SidepanelSettings />} />
|
||||
|
@ -6,5 +6,9 @@ export const SUPPORTED_SERACH_PROVIDERS = [
|
||||
{
|
||||
label: "DuckDuckGo",
|
||||
value: "duckduckgo"
|
||||
},
|
||||
{
|
||||
label: "Sogou",
|
||||
value: "sogou"
|
||||
}
|
||||
]
|
@ -95,7 +95,7 @@ export const webDuckDuckGoSearch = async (query: string) => {
|
||||
const textSplitter = new RecursiveCharacterTextSplitter({
|
||||
chunkSize,
|
||||
chunkOverlap
|
||||
})
|
||||
})
|
||||
|
||||
const chunks = await textSplitter.splitDocuments(docs)
|
||||
|
127
src/web/search-engines/sogou.ts
Normal file
127
src/web/search-engines/sogou.ts
Normal file
@ -0,0 +1,127 @@
|
||||
import { cleanUrl } from "@/libs/clean-url"
|
||||
import { chromeRunTime } from "@/libs/runtime"
|
||||
import { PageAssistHtmlLoader } from "@/loader/html"
|
||||
import {
|
||||
defaultEmbeddingChunkOverlap,
|
||||
defaultEmbeddingChunkSize,
|
||||
defaultEmbeddingModelForRag,
|
||||
getOllamaURL
|
||||
} from "@/services/ollama"
|
||||
import {
|
||||
getIsSimpleInternetSearch,
|
||||
totalSearchResults
|
||||
} from "@/services/search"
|
||||
import { OllamaEmbeddings } from "@langchain/community/embeddings/ollama"
|
||||
import type { Document } from "@langchain/core/documents"
|
||||
import * as cheerio from "cheerio"
|
||||
import { RecursiveCharacterTextSplitter } from "langchain/text_splitter"
|
||||
import { MemoryVectorStore } from "langchain/vectorstores/memory"
|
||||
const getCorrectTargeUrl = async (url: string) => {
|
||||
if (!url) return ""
|
||||
const res = await fetch(url)
|
||||
const $ = cheerio.load(await res.text())
|
||||
const link = $("script").text()
|
||||
const matches = link.match(/"(.*?)"/)
|
||||
return matches?.[1] || ""
|
||||
}
|
||||
export const localSogouSearch = async (query: string) => {
|
||||
await chromeRunTime(cleanUrl("https://www.sogou.com/web?query=" + query))
|
||||
|
||||
const abortController = new AbortController()
|
||||
|
||||
setTimeout(() => abortController.abort(), 10000)
|
||||
|
||||
const htmlString = await fetch("https://www.sogou.com/web?query=" + query, {
|
||||
signal: abortController.signal
|
||||
})
|
||||
.then((response) => response.text())
|
||||
.catch()
|
||||
|
||||
const $ = cheerio.load(htmlString)
|
||||
const $result = $("#main .results")
|
||||
const nodes = $result.children().map(async (i, el) => {
|
||||
const $el = $(el)
|
||||
const title = $el.find(".vr-title").text().replace(/\n/g, "").trim()
|
||||
let link = $el.find(".vr-title > a").get(0)?.attribs.href
|
||||
const content = [".star-wiki", ".fz-mid", ".attribute-centent"]
|
||||
.map((selector) => {
|
||||
;[".text-lightgray", ".zan-box", ".tag-website"].forEach((cls) => {
|
||||
$el.find(cls).remove()
|
||||
})
|
||||
return $el.find(selector).text().trim() ?? ""
|
||||
})
|
||||
.join(" ")
|
||||
if (link?.startsWith("/")) {
|
||||
link = await getCorrectTargeUrl(`https://www.sogou.com${link}`)
|
||||
}
|
||||
return { title, link, content }
|
||||
})
|
||||
|
||||
const searchResults = await Promise.all(nodes)
|
||||
return searchResults.filter(
|
||||
(result) => result.link && result.title && result.content
|
||||
)
|
||||
}
|
||||
|
||||
export const webSogouSearch = async (query: string) => {
|
||||
const results = await localSogouSearch(query)
|
||||
const TOTAL_SEARCH_RESULTS = await totalSearchResults()
|
||||
const searchResults = results.slice(0, TOTAL_SEARCH_RESULTS)
|
||||
|
||||
const isSimpleMode = await getIsSimpleInternetSearch()
|
||||
|
||||
if (isSimpleMode) {
|
||||
await getOllamaURL()
|
||||
return searchResults.map((result) => {
|
||||
return {
|
||||
url: result.link,
|
||||
content: result.content
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
const docs: Document<Record<string, any>>[] = []
|
||||
for (const result of searchResults) {
|
||||
const loader = new PageAssistHtmlLoader({
|
||||
html: "",
|
||||
url: result.link
|
||||
})
|
||||
|
||||
const documents = await loader.loadByURL()
|
||||
|
||||
documents.forEach((doc) => {
|
||||
docs.push(doc)
|
||||
})
|
||||
}
|
||||
const ollamaUrl = await getOllamaURL()
|
||||
|
||||
const embeddingModle = await defaultEmbeddingModelForRag()
|
||||
const ollamaEmbedding = new OllamaEmbeddings({
|
||||
model: embeddingModle || "",
|
||||
baseUrl: cleanUrl(ollamaUrl)
|
||||
})
|
||||
|
||||
const chunkSize = await defaultEmbeddingChunkSize()
|
||||
const chunkOverlap = await defaultEmbeddingChunkOverlap()
|
||||
const textSplitter = new RecursiveCharacterTextSplitter({
|
||||
chunkSize,
|
||||
chunkOverlap
|
||||
})
|
||||
|
||||
const chunks = await textSplitter.splitDocuments(docs)
|
||||
|
||||
const store = new MemoryVectorStore(ollamaEmbedding)
|
||||
|
||||
await store.addDocuments(chunks)
|
||||
|
||||
const resultsWithEmbeddings = await store.similaritySearch(query, 3)
|
||||
|
||||
const searchResult = resultsWithEmbeddings.map((result) => {
|
||||
return {
|
||||
url: result.metadata.url,
|
||||
content: result.pageContent
|
||||
}
|
||||
})
|
||||
|
||||
return searchResult
|
||||
}
|
@ -1,7 +1,8 @@
|
||||
import { getWebSearchPrompt } from "~/services/ollama"
|
||||
import { webGoogleSearch } from "./local-google"
|
||||
import { webDuckDuckGoSearch } from "./local-duckduckgo"
|
||||
import { webGoogleSearch } from "./search-engines/google"
|
||||
import { webDuckDuckGoSearch } from "./search-engines/duckduckgo"
|
||||
import { getSearchProvider } from "@/services/search"
|
||||
import { webSogouSearch } from "./search-engines/sogou"
|
||||
|
||||
const getHostName = (url: string) => {
|
||||
try {
|
||||
@ -16,6 +17,8 @@ const searchWeb = (provider: string, query: string) => {
|
||||
switch (provider) {
|
||||
case "duckduckgo":
|
||||
return webDuckDuckGoSearch(query)
|
||||
case "sogou":
|
||||
return webSogouSearch(query)
|
||||
default:
|
||||
return webGoogleSearch(query)
|
||||
}
|
||||
|
@ -24,7 +24,7 @@ export default defineConfig({
|
||||
srcDir: "src",
|
||||
outDir: "build",
|
||||
manifest: {
|
||||
version: "1.1.4",
|
||||
version: "1.1.5",
|
||||
name: '__MSG_extName__',
|
||||
description: '__MSG_extDescription__',
|
||||
default_locale: 'en',
|
||||
|
Loading…
x
Reference in New Issue
Block a user