commit
914e358ee8
@ -193,7 +193,9 @@
|
|||||||
},
|
},
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "Are you sure you want to delete this share? This action cannot be undone."
|
"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": {
|
"notification": {
|
||||||
"pageShareSuccess": "Page Share URL updated successfully",
|
"pageShareSuccess": "Page Share URL updated successfully",
|
||||||
|
@ -196,7 +196,9 @@
|
|||||||
},
|
},
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "本当にこの共有を削除しますか?この操作は元に戻せません。"
|
"delete": "本当にこの共有を削除しますか?この操作は元に戻せません。"
|
||||||
}
|
},
|
||||||
|
"label": "ページ共有を管理する",
|
||||||
|
"description": "ページ共有機能を有効または無効にします。デフォルトでは、ページ共有機能は有効になっています。"
|
||||||
},
|
},
|
||||||
"notification": {
|
"notification": {
|
||||||
"pageShareSuccess": "ページ共有URLが正常に更新されました",
|
"pageShareSuccess": "ページ共有URLが正常に更新されました",
|
||||||
|
@ -196,7 +196,9 @@
|
|||||||
},
|
},
|
||||||
"confirm": {
|
"confirm": {
|
||||||
"delete": "ഈ പങ്കിടല് ഇല്ലാതാക്കണമെന്ന് തീർച്ചയാണോ? ഈ പ്രവർത്തനം പിന്നീട് പിൻവലിക്കാനാകില്ല."
|
"delete": "ഈ പങ്കിടല് ഇല്ലാതാക്കണമെന്ന് തീർച്ചയാണോ? ഈ പ്രവർത്തനം പിന്നീട് പിൻവലിക്കാനാകില്ല."
|
||||||
}
|
},
|
||||||
|
"label": "പേജ് ഷെയർ നിയന്ത്രിക്കുക",
|
||||||
|
"description": "പേജ് ഷെയർ സവിശേഷത സജീവമാക്കുകയോ അക്ഷമമാക്കുകയോ ചെയ്യുക. സ്ഥിരംമായി, പേജ് ഷെയർ സവിശേഷത സജീവമാക്കപ്പെടുന്നു."
|
||||||
},
|
},
|
||||||
"notification": {
|
"notification": {
|
||||||
"pageShareSuccess": "പേജ് പങ്കിടാനുള്ള URL വിജയകരമായി അപ്ഡേറ്റ് ചെയ്തു",
|
"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": {
|
"confirm": {
|
||||||
"delete": "您确定要删除此对话共享吗?这个操作不能撤销。"
|
"delete": "您确定要删除此对话共享吗?这个操作不能撤销。"
|
||||||
}
|
},
|
||||||
|
"label": "管理页面分享",
|
||||||
|
"description": "启用或禁用页面分享功能。默认情况下,页面分享功能已启用。"
|
||||||
},
|
},
|
||||||
"notification": {
|
"notification": {
|
||||||
"pageShareSuccess": "对话共享服务 URL 已成功更新",
|
"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-face {
|
||||||
font-family: "font";
|
font-family: "Inter";
|
||||||
src: url("font.ttf") format("truetype");
|
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;
|
@tailwind base;
|
||||||
|
@ -20,6 +20,7 @@ import { ShareBtn } from "~/components/Common/ShareBtn"
|
|||||||
import { useTranslation } from "react-i18next"
|
import { useTranslation } from "react-i18next"
|
||||||
import { OllamaIcon } from "../Icons/Ollama"
|
import { OllamaIcon } from "../Icons/Ollama"
|
||||||
import { SelectedKnowledge } from "../Option/Knowledge/SelectedKnwledge"
|
import { SelectedKnowledge } from "../Option/Knowledge/SelectedKnwledge"
|
||||||
|
import { useStorage } from "@plasmohq/storage/hook"
|
||||||
|
|
||||||
export default function OptionLayout({
|
export default function OptionLayout({
|
||||||
children
|
children
|
||||||
@ -28,6 +29,7 @@ export default function OptionLayout({
|
|||||||
}) {
|
}) {
|
||||||
const [sidebarOpen, setSidebarOpen] = useState(false)
|
const [sidebarOpen, setSidebarOpen] = useState(false)
|
||||||
const { t } = useTranslation(["option", "common"])
|
const { t } = useTranslation(["option", "common"])
|
||||||
|
const [shareModeEnabled] = useStorage("shareMode", true)
|
||||||
|
|
||||||
const {
|
const {
|
||||||
selectedModel,
|
selectedModel,
|
||||||
@ -175,9 +177,10 @@ export default function OptionLayout({
|
|||||||
<div className="flex flex-1 justify-end px-4">
|
<div className="flex flex-1 justify-end px-4">
|
||||||
<div className="ml-4 flex items-center md:ml-6">
|
<div className="ml-4 flex items-center md:ml-6">
|
||||||
<div className="flex gap-4 items-center">
|
<div className="flex gap-4 items-center">
|
||||||
{pathname === "/" && messages.length > 0 && !streaming && (
|
{pathname === "/" &&
|
||||||
<ShareBtn messages={messages} />
|
messages.length > 0 &&
|
||||||
)}
|
!streaming &&
|
||||||
|
shareModeEnabled && <ShareBtn messages={messages} />}
|
||||||
<Tooltip title={t("githubRepository")}>
|
<Tooltip title={t("githubRepository")}>
|
||||||
<a
|
<a
|
||||||
href="https://github.com/n4ze3m/page-assist"
|
href="https://github.com/n4ze3m/page-assist"
|
||||||
|
@ -1,15 +1,17 @@
|
|||||||
import { useMutation, useQuery, useQueryClient } from "@tanstack/react-query"
|
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 { Trash2 } from "lucide-react"
|
||||||
import { Trans, useTranslation } from "react-i18next"
|
import { Trans, useTranslation } from "react-i18next"
|
||||||
import { SaveButton } from "~/components/Common/SaveButton"
|
import { SaveButton } from "~/components/Common/SaveButton"
|
||||||
import { deleteWebshare, getAllWebshares, getUserId } from "@/db"
|
import { deleteWebshare, getAllWebshares, getUserId } from "@/db"
|
||||||
import { getPageShareUrl, setPageShareUrl } from "~/services/ollama"
|
import { getPageShareUrl, setPageShareUrl } from "~/services/ollama"
|
||||||
import { verifyPageShareURL } from "~/utils/verify-page-share"
|
import { verifyPageShareURL } from "~/utils/verify-page-share"
|
||||||
|
import { useStorage } from "@plasmohq/storage/hook"
|
||||||
|
|
||||||
export const OptionShareBody = () => {
|
export const OptionShareBody = () => {
|
||||||
const queryClient = useQueryClient()
|
const queryClient = useQueryClient()
|
||||||
const { t } = useTranslation(["settings"])
|
const { t } = useTranslation(["settings"])
|
||||||
|
const [shareModeEnabled, setShareModelEnabled] = useStorage("shareMode", true)
|
||||||
|
|
||||||
const { status, data } = useQuery({
|
const { status, data } = useQuery({
|
||||||
queryKey: ["fetchShareInfo"],
|
queryKey: ["fetchShareInfo"],
|
||||||
@ -132,6 +134,20 @@ export const OptionShareBody = () => {
|
|||||||
</div>
|
</div>
|
||||||
</Form.Item>
|
</Form.Item>
|
||||||
</Form>
|
</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>
|
<div>
|
||||||
<div>
|
<div>
|
||||||
|
@ -11,13 +11,16 @@ import { PageAssistProvider } from "@/components/Common/PageAssistProvider"
|
|||||||
|
|
||||||
function IndexOption() {
|
function IndexOption() {
|
||||||
const { mode } = useDarkMode()
|
const { mode } = useDarkMode()
|
||||||
const { t } = useTranslation()
|
const { t, i18n } = useTranslation()
|
||||||
return (
|
return (
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<ConfigProvider
|
<ConfigProvider
|
||||||
theme={{
|
theme={{
|
||||||
algorithm:
|
algorithm:
|
||||||
mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm
|
mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm,
|
||||||
|
token: {
|
||||||
|
fontFamily: i18n.language === "ru" ? "Onest" : "Inter"
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
renderEmpty={() => (
|
renderEmpty={() => (
|
||||||
<Empty
|
<Empty
|
||||||
|
@ -11,14 +11,17 @@ import { PageAssistProvider } from "@/components/Common/PageAssistProvider"
|
|||||||
|
|
||||||
function IndexSidepanel() {
|
function IndexSidepanel() {
|
||||||
const { mode } = useDarkMode()
|
const { mode } = useDarkMode()
|
||||||
const { t } = useTranslation()
|
const { t, i18n } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<MemoryRouter>
|
<MemoryRouter>
|
||||||
<ConfigProvider
|
<ConfigProvider
|
||||||
theme={{
|
theme={{
|
||||||
algorithm:
|
algorithm:
|
||||||
mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm
|
mode === "dark" ? theme.darkAlgorithm : theme.defaultAlgorithm,
|
||||||
|
token: {
|
||||||
|
fontFamily: i18n.language === "ru" ? "Onest" : "Inter"
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
renderEmpty={() => (
|
renderEmpty={() => (
|
||||||
<Empty
|
<Empty
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
import i18n from "i18next";
|
import i18n from "i18next";
|
||||||
import { initReactI18next } from "react-i18next";
|
import { initReactI18next } from "react-i18next";
|
||||||
import { en } from "./lang/en";
|
import { en } from "./lang/en";
|
||||||
|
import { ru } from "./lang/ru";
|
||||||
import { ml } from "./lang/ml";
|
import { ml } from "./lang/ml";
|
||||||
import { zh } from "./lang/zh";
|
import { zh } from "./lang/zh";
|
||||||
import { ja } from "./lang/ja";
|
import { ja } from "./lang/ja";
|
||||||
@ -14,6 +15,8 @@ i18n
|
|||||||
en: en,
|
en: en,
|
||||||
ml: ml,
|
ml: ml,
|
||||||
"zh-CN": zh,
|
"zh-CN": zh,
|
||||||
|
ru: ru,
|
||||||
|
"ru-RU": ru,
|
||||||
zh: zh,
|
zh: zh,
|
||||||
ja: ja,
|
ja: ja,
|
||||||
"ja-JP": 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",
|
label: "English",
|
||||||
value: "en"
|
value: "en"
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
label: "Russian",
|
||||||
|
value: "ru"
|
||||||
|
},
|
||||||
{
|
{
|
||||||
label: "മലയാളം",
|
label: "മലയാളം",
|
||||||
value: "ml"
|
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 { OptionShare } from "./option-settings-share"
|
||||||
import { OptionKnowledgeBase } from "./option-settings-knowledge"
|
import { OptionKnowledgeBase } from "./option-settings-knowledge"
|
||||||
import { OptionAbout } from "./option-settings-about"
|
import { OptionAbout } from "./option-settings-about"
|
||||||
|
import { useTranslation } from "react-i18next"
|
||||||
|
|
||||||
export const OptionRouting = () => {
|
export const OptionRouting = () => {
|
||||||
const { mode } = useDarkMode()
|
const { mode } = useDarkMode()
|
||||||
|
const { i18n } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={mode === "dark" ? "dark" : "light"}>
|
<div
|
||||||
|
className={`${mode === "dark" ? "dark" : "light"} ${
|
||||||
|
i18n.language === "ru" ? "onest" : "inter"
|
||||||
|
}`}>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<OptionIndex />} />
|
<Route path="/" element={<OptionIndex />} />
|
||||||
<Route path="/settings" element={<OptionSettings />} />
|
<Route path="/settings" element={<OptionSettings />} />
|
||||||
@ -32,9 +37,13 @@ export const OptionRouting = () => {
|
|||||||
|
|
||||||
export const SidepanelRouting = () => {
|
export const SidepanelRouting = () => {
|
||||||
const { mode } = useDarkMode()
|
const { mode } = useDarkMode()
|
||||||
|
const { i18n } = useTranslation()
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className={mode === "dark" ? "dark" : "light"}>
|
<div
|
||||||
|
className={`${mode === "dark" ? "dark" : "light"} ${
|
||||||
|
i18n.language === "ru" ? "onest" : "inter"
|
||||||
|
}`}>
|
||||||
<Routes>
|
<Routes>
|
||||||
<Route path="/" element={<SidepanelChat />} />
|
<Route path="/" element={<SidepanelChat />} />
|
||||||
<Route path="/settings" element={<SidepanelSettings />} />
|
<Route path="/settings" element={<SidepanelSettings />} />
|
||||||
|
@ -6,5 +6,9 @@ export const SUPPORTED_SERACH_PROVIDERS = [
|
|||||||
{
|
{
|
||||||
label: "DuckDuckGo",
|
label: "DuckDuckGo",
|
||||||
value: "duckduckgo"
|
value: "duckduckgo"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
label: "Sogou",
|
||||||
|
value: "sogou"
|
||||||
}
|
}
|
||||||
]
|
]
|
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 { getWebSearchPrompt } from "~/services/ollama"
|
||||||
import { webGoogleSearch } from "./local-google"
|
import { webGoogleSearch } from "./search-engines/google"
|
||||||
import { webDuckDuckGoSearch } from "./local-duckduckgo"
|
import { webDuckDuckGoSearch } from "./search-engines/duckduckgo"
|
||||||
import { getSearchProvider } from "@/services/search"
|
import { getSearchProvider } from "@/services/search"
|
||||||
|
import { webSogouSearch } from "./search-engines/sogou"
|
||||||
|
|
||||||
const getHostName = (url: string) => {
|
const getHostName = (url: string) => {
|
||||||
try {
|
try {
|
||||||
@ -16,6 +17,8 @@ const searchWeb = (provider: string, query: string) => {
|
|||||||
switch (provider) {
|
switch (provider) {
|
||||||
case "duckduckgo":
|
case "duckduckgo":
|
||||||
return webDuckDuckGoSearch(query)
|
return webDuckDuckGoSearch(query)
|
||||||
|
case "sogou":
|
||||||
|
return webSogouSearch(query)
|
||||||
default:
|
default:
|
||||||
return webGoogleSearch(query)
|
return webGoogleSearch(query)
|
||||||
}
|
}
|
||||||
|
@ -24,7 +24,7 @@ export default defineConfig({
|
|||||||
srcDir: "src",
|
srcDir: "src",
|
||||||
outDir: "build",
|
outDir: "build",
|
||||||
manifest: {
|
manifest: {
|
||||||
version: "1.1.4",
|
version: "1.1.5",
|
||||||
name: '__MSG_extName__',
|
name: '__MSG_extName__',
|
||||||
description: '__MSG_extDescription__',
|
description: '__MSG_extDescription__',
|
||||||
default_locale: 'en',
|
default_locale: 'en',
|
||||||
|
Loading…
x
Reference in New Issue
Block a user