mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
@ -87,7 +87,7 @@
|
||||
}
|
||||
|
||||
#rm_group_members:empty::before {
|
||||
content: 'Group is empty';
|
||||
content: attr(group_empty_text);
|
||||
|
||||
font-weight: bolder;
|
||||
width: 100%;
|
||||
@ -115,7 +115,7 @@
|
||||
}
|
||||
|
||||
#rm_group_add_members:empty::before {
|
||||
content: 'No characters available';
|
||||
content: attr(no_characters_text);
|
||||
|
||||
font-weight: bolder;
|
||||
width: 100%;
|
||||
|
@ -2052,8 +2052,8 @@
|
||||
<div class="flex-container oneline-dropdown" title="Constrains effort on reasoning for reasoning models. Reducing reasoning effort can result in faster responses and fewer tokens used on reasoning in a response." data-i18n="[title]Constrains effort on reasoning for reasoning models.">
|
||||
<label for="openai_reasoning_effort">
|
||||
<span data-i18n="Reasoning Effort">Reasoning Effort</span>
|
||||
<i data-source="openai,custom,xai,openrouter" class="opacity50p fa-solid fa-circle-info" title="OpenAI-style options: low, medium, high. Minimum and maximum are aliased to low and high. Auto does not send an effort level."></i>
|
||||
<i data-source="claude,makersuite" class="opacity50p fa-solid fa-circle-info" title="Allocates a portion of the response length for thinking (low: 10%, medium: 25%, high: 50%). Other options are model-dependent."></i>
|
||||
<i data-source="openai,custom,xai,openrouter" class="opacity50p fa-solid fa-circle-info" title="OpenAI-style options: low, medium, high. Minimum and maximum are aliased to low and high. Auto does not send an effort level." data-i18n="[title]OpenAI-style options: low, medium, high. Minimum and maximum are aliased to low and high. Auto does not send an effort level."></i>
|
||||
<i data-source="claude,makersuite" class="opacity50p fa-solid fa-circle-info" title="Allocates a portion of the response length for thinking (low: 10%, medium: 25%, high: 50%). Other options are model-dependent." data-i18n="[title]Allocates a portion of the response length for thinking (low: 10%, medium: 25%, high: 50%). Other options are model-dependent."></i>
|
||||
</label>
|
||||
<select id="openai_reasoning_effort">
|
||||
<option data-i18n="openai_reasoning_effort_auto" value="auto">Auto</option>
|
||||
@ -2498,8 +2498,8 @@
|
||||
<option value="search" data-i18n="Search" hidden>A-Z</option>
|
||||
<option value="asc">A-Z</option>
|
||||
<option value="desc">Z-A</option>
|
||||
<option value="date_asc">Date Asc</option>
|
||||
<option value="date_desc">Date Desc</option>
|
||||
<option data-i18n="Date Asc" value="date_asc">Date Asc</option>
|
||||
<option data-i18n="Date Desc" value="date_desc">Date Desc</option>
|
||||
</select>
|
||||
<select id="featherless_category_selection" class="text_pole">
|
||||
<option value="" disabled selected data-i18n="category">category</option>
|
||||
@ -2509,7 +2509,7 @@
|
||||
<option value="All" data-i18n="All">All</option>
|
||||
</select>
|
||||
<select id="featherless_class_selection" class="text_pole">
|
||||
<option value="" selected data-i18n="class">All Classes</option>
|
||||
<option value="" selected data-i18n="All Classes">All Classes</option>
|
||||
</select>
|
||||
<div id="featherless_model_pagination_container" class="flex1"></div>
|
||||
<i id="featherless_model_grid_toggle" class="fa-solid fa-table-cells-large menu_button" data-i18n="[title]Toggle grid view" title="Toggle grid view"></i>
|
||||
@ -5531,7 +5531,7 @@
|
||||
<div class="inline-drawer-content">
|
||||
<div id="currentGroupMembers" name="Current Group Members" class="flex-container flexFlowColumn overflowYAuto flex1">
|
||||
<div id="rm_group_members_pagination" class="rm_group_members_pagination group_pagination"></div>
|
||||
<div id="rm_group_members" class="rm_group_members overflowYAuto flex-container"></div>
|
||||
<div id="rm_group_members" class="rm_group_members overflowYAuto flex-container" group_empty_text="Group is empty." data-i18n="[group_empty_text]Group is empty."></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -5549,7 +5549,7 @@
|
||||
<div class="tags rm_tag_filter"></div>
|
||||
</div>
|
||||
<div id="rm_group_add_members_pagination" class="group_pagination"></div>
|
||||
<div id="rm_group_add_members" class="overflowYAuto flex-container"></div>
|
||||
<div id="rm_group_add_members" class="overflowYAuto flex-container" no_characters_text="No characters available" data-i18n="[no_characters_text]No characters available"></div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@ -5969,7 +5969,7 @@
|
||||
<div class="tag_view_color_picker" data-value="color"></div>
|
||||
<div class="tag_view_color_picker" data-value="color2"></div>
|
||||
<div class="tag_view_name" contenteditable="true"></div>
|
||||
<div class="tag_view_counter"><span class="tag_view_counter_value"></span> entries</div>
|
||||
<div class="tag_view_counter"><span class="tag_view_counter_value"></span> <span data-i18n="tag_entries">entries</span></div>
|
||||
<div title="Delete tag" class="tag_delete fa-solid fa-trash-can right_menu_button" data-i18n="[title]Delete tag"></div>
|
||||
</div>
|
||||
</div>
|
||||
@ -6704,7 +6704,7 @@
|
||||
</div>
|
||||
<div class="flex-container wide100pLess70px character_select_container height100p alignitemscenter">
|
||||
<div class="wide100p character_name_block">
|
||||
<span class="ch_name">Go back</span>
|
||||
<span class="ch_name" data-i18n="Go back">Go back</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -52,7 +52,7 @@
|
||||
"Presence Penalty": "Штраф за присутствие",
|
||||
"Top A": "Top А",
|
||||
"Tail Free Sampling": "Tail Free Sampling",
|
||||
"Rep. Pen. Slope": "Rep. Pen. Slope",
|
||||
"Rep. Pen. Slope": "Рост штрафа за повтор к концу промпта",
|
||||
"Top K": "Top K",
|
||||
"Top P": "Top P",
|
||||
"Do Sample": "Включить сэмплинг",
|
||||
@ -162,9 +162,9 @@
|
||||
"Story String": "Строка истории",
|
||||
"Example Separator": "Разделитель примеров сообщений",
|
||||
"Chat Start": "Начало чата",
|
||||
"Activation Regex": "Regex для активации",
|
||||
"Activation Regex": "Рег. выражение для активации",
|
||||
"Instruct Mode": "Режим Instruct",
|
||||
"Wrap Sequences with Newline": "Отделять строки символом новой строки",
|
||||
"Wrap Sequences with Newline": "Каждая строка из шаблона на новой строке",
|
||||
"Include Names": "Добавлять имена",
|
||||
"Force for Groups and Personas": "Также для групп и персон",
|
||||
"System Prompt": "Системный промпт",
|
||||
@ -299,7 +299,7 @@
|
||||
"AI Horde": "AI Horde",
|
||||
"NovelAI": "NovelAI",
|
||||
"OpenAI API key": "Ключ для API OpenAI",
|
||||
"Trim spaces": "Обрезать пробелы",
|
||||
"Trim spaces": "Обрезать пробелы в начале и конце",
|
||||
"Trim Incomplete Sentences": "Удалять неоконченные предложения",
|
||||
"Include Newline": "Добавлять новую строку",
|
||||
"Non-markdown strings": "Строки без разметки",
|
||||
@ -510,7 +510,7 @@
|
||||
"New preset": "Новый пресет",
|
||||
"Delete preset": "Удалить пресет",
|
||||
"API Connections": "Соединения с API",
|
||||
"Can help with bad responses by queueing only the approved workers. May slowdown the response time.": "Может помочь с плохими ответами ставя в очередь только подтвержденных работников. Может замедлить время ответа.",
|
||||
"Can help with bad responses by queueing only the approved workers. May slowdown the response time.": "Может помочь при плохих ответах, делая запросы только к доверенным рабочим машинам. Может замедлить время ответа.",
|
||||
"Clear your API key": "Стереть ключ от API",
|
||||
"Refresh models": "Обновить модели",
|
||||
"Get your OpenRouter API token using OAuth flow. You will be redirected to openrouter.ai": "Получите свой OpenRouter API токен используя OAuth. У вас будет открыта вкладка openrouter.ai",
|
||||
@ -551,7 +551,7 @@
|
||||
"Token counts may be inaccurate and provided just for reference.": "Счетчик токенов может быть неточным, используйте как ориентир",
|
||||
"Click to select a new avatar for this character": "Нажмите чтобы выбрать новый аватар для этого персонажа",
|
||||
"Example: [{{user}} is a 28-year-old Romanian cat girl.]": "Пример:\n [{{user}} is a 28-year-old Romanian cat girl.]",
|
||||
"Toggle grid view": "Переключить вид сетки",
|
||||
"Toggle grid view": "Сменить вид сетки",
|
||||
"Add to Favorites": "Добавить в Избранное",
|
||||
"Advanced Definition": "Расширенное описание",
|
||||
"Character Lore": "Лор персонажа",
|
||||
@ -624,7 +624,7 @@
|
||||
"UI Theme": "Тема UI",
|
||||
"This message is invisible for the AI": "Это сообщение невидимо для ИИ",
|
||||
"Sampler Priority": "Приоритет сэмплеров",
|
||||
"Ooba only. Determines the order of samplers.": "Только oobabooga. Определяет порядок сэмплеров.",
|
||||
"Ooba only. Determines the order of samplers.": "Только для oobabooga. Определяет порядок сэмплеров.",
|
||||
"Load default order": "Загрузить стандартный порядок",
|
||||
"Max Tokens Second": "Макс. кол-во токенов в секунду",
|
||||
"CFG": "CFG",
|
||||
@ -695,7 +695,7 @@
|
||||
"Medium": "Средний",
|
||||
"Aggressive": "Агрессивный",
|
||||
"Very aggressive": "Очень агрессивный",
|
||||
"Eta_Cutoff_desc": "Eta cutoff - основной параметр специальной техники сэмплинга под названием Eta Sampling. В единицах 1e-4; разумное значение - 3. Установите в 0, чтобы отключить. См. статью Truncation Sampling as Language Model Desmoothing от Хьюитт и др. (2022) для получения подробной информации.",
|
||||
"Eta_Cutoff_desc": "Eta cutoff - основной параметр специальной техники сэмплинга под названием Eta Sampling.\nВ единицах 1e-4; разумное значение - 3.\nУстановите в 0, чтобы отключить.\nСм. статью Truncation Sampling as Language Model Desmoothing от Хьюитт и др. (2022) для получения подробной информации.",
|
||||
"Learn how to contribute your idle GPU cycles to the Horde": "Узнайте, как использовать время простоя вашего GPU для помощи Horde",
|
||||
"Use the appropriate tokenizer for Google models via their API. Slower prompt processing, but offers much more accurate token counting.": "Используйте соответствующий токенизатор для моделей Google через их API. Медленная обработка подсказок, но предлагает намного более точный подсчет токенов.",
|
||||
"Load koboldcpp order": "Загрузить порядок из koboldcpp",
|
||||
@ -964,7 +964,7 @@
|
||||
"char_import_3": "Персонаж с JanitorAI (прямая ссылка или UUID)",
|
||||
"char_import_4": "Персонаж с Pygmalion.chat (прямая ссылка или UUID)",
|
||||
"char_import_5": "Персонаж с AICharacterCards.com (прямая ссылка или ID)",
|
||||
"char_import_6": "Прямая ссылка на PNG-файл (чтобы узнать список разрешённых хостов, загляните в",
|
||||
"char_import_6": "Прямая ссылка на PNG-файл (список разрешённых хостов находится в",
|
||||
"char_import_7": ")",
|
||||
"Grammar String": "Грамматика",
|
||||
"GBNF or EBNF, depends on the backend in use. If you're using this you should know which.": "GBNF или EBNF, зависит от бэкенда. Если вы это используете, то, скорее всего, сами знаете, какой именно.",
|
||||
@ -1016,7 +1016,7 @@
|
||||
"prompt_manager_relative": "Относительная",
|
||||
"prompt_manager_depth": "Глубина",
|
||||
"Injection depth. 0 = after the last message, 1 = before the last message, etc.": "Глубина вставки. 0 = после последнего сообщения, 1 = перед последним сообщением, и т.д.",
|
||||
"The prompt to be sent.": "Отправляемый ИИ промпт.",
|
||||
"The prompt to be sent.": "Текст промпта.",
|
||||
"prompt_manager_forbid_overrides": "Запретить перезапись",
|
||||
"This prompt cannot be overridden by character cards, even if overrides are preferred.": "Карточка персонажа не сможет перезаписать этот промпт, даже если настройки отдают приоритет именно ей.",
|
||||
"image_inlining_hint_1": "Отправлять картинки как часть промпта, если позволяет модель (такой функционал поддерживают GPT-4V, Claude 3 или Llava 13B). Чтобы добавить в чат изображение, используйте на нужном сообщении действие",
|
||||
@ -1232,7 +1232,7 @@
|
||||
"Top P & Min P": "Top P & Min P",
|
||||
"llama.cpp only. Determines the order of samplers. If Mirostat mode is not 0, sampler order is ignored.": "llama.cpp only. Determines the order of samplers. If Mirostat mode is not 0, sampler order is ignored.",
|
||||
"Helps the model to associate messages with characters.": "Помогает модели связывать сообщения с персонажами.",
|
||||
"character_names_default": "Except for groups and past personas. Otherwise, make sure you provide names in the prompt.",
|
||||
"character_names_default": "Добавлять префиксы для групповых чатов и предыдущих персон. В остальных случаях указывайте имена в промпте иными способами.",
|
||||
"Completion": "Completion Object",
|
||||
"character_names_completion": "Только латинские буквы, цифры и знак подчёркивания. Работает не для всех бэкендов, в частности для Claude, MistralAI, Google.",
|
||||
"Use AI21 Tokenizer": "Использовать токенайзер AI21",
|
||||
@ -1277,7 +1277,7 @@
|
||||
"Will be inserted as a last prompt line when using system/neutral generation.": "Will be inserted as a last prompt line when using system/neutral generation.",
|
||||
"If a stop sequence is generated, everything past it will be removed from the output (inclusive).": "Если ИИ генерирует стоп-строку, то всё после неё будет вырезано из ответа (включая и саму стоп-строку).",
|
||||
"Will be inserted at the start of the chat history if it doesn't start with a User message.": "Вставляется в начале истории чата, если она начинается не с сообщения пользователя.",
|
||||
"Global World Info/Lorebook activation settings": "Настройки активации глобального лорбука / Информации о мире",
|
||||
"Global World Info/Lorebook activation settings": "Глобальные настройки активации лорбука / Информации о мире",
|
||||
"Click to expand": "Щёлкните, чтобы развернуть",
|
||||
"Insertion Strategy": "Как инжектить",
|
||||
"Only the entries with the most number of key matches will be selected for Inclusion Group filtering": "Only the entries with the most number of key matches will be selected for Inclusion Group filtering",
|
||||
@ -1646,8 +1646,8 @@
|
||||
"mui_reset": "Сброс",
|
||||
"Quick 'Impersonate' button": "Быстрое перевоплощение",
|
||||
"Show a button in the input area to ask the AI to impersonate your character for a single message": "Показать в поле ввода кнопку, по нажатии на которую ИИ сгенерирует одно сообщение от лица вашего персонажа.",
|
||||
"Separators as Stop Strings": "Разделители как стоп-строки",
|
||||
"Names as Stop Strings": "Имена как стоп-строки",
|
||||
"Separators as Stop Strings": "Разделители в качестве стоп-строк",
|
||||
"Names as Stop Strings": "Имена в качестве стоп-строк",
|
||||
"Add Character and User names to a list of stopping strings.": "Добавлять имена персонажа и пользователя в список стоп-строк.",
|
||||
"context_allow_post_history_instructions": "Добавлять в конец промпта инструкции после истории. Работает только при наличии таких инструкций в карточке И при включенной опции ''Приоритет инструкциям из карточек''.\nНЕ РЕКОМЕНДУЕТСЯ ДЛЯ МОДЕЛЕЙ TEXT COMPLETION, МОЖЕТ ПОРТИТЬ ВЫХОДНОЙ ТЕКСТ.",
|
||||
"First User Prefix": "Первый префикс пользователя",
|
||||
@ -1914,8 +1914,8 @@
|
||||
"Cannot restore GUI preset": "Пресет для Gui восстановить нельзя",
|
||||
"Default preset cannot be restored": "Невозможно восстановить пресет по умолчанию",
|
||||
"Default template cannot be restored": "Невозможно восстановить шаблон по умолчанию",
|
||||
"Resetting a <b>default preset</b> will restore the default settings": "Сброс <b>стандартного пресета</b> восстановит настройки по умолчанию.",
|
||||
"Resetting a <b>default template</b> will restore the default settings.": "Сброс <b>стандартного шаблона</b> восстановит настройки по умолчанию.",
|
||||
"Resetting a <b>default preset</b> will restore the default settings.": "Сброс <b>комплектного пресета</b> восстановит настройки по умолчанию.",
|
||||
"Resetting a <b>default template</b> will restore the default settings.": "Сброс <b>комплектного шаблона</b> восстановит настройки по умолчанию.",
|
||||
"Are you sure?": "Вы уверены?",
|
||||
"Default preset restored": "Стандартный пресет восстановлен",
|
||||
"Default template restored": "Стандартный шаблон восстановлен",
|
||||
@ -2046,11 +2046,11 @@
|
||||
"prompt_post_processing_merge": "Объединять идущие подряд сообщения с одной ролью",
|
||||
"prompt_post_processing_semi": "Semi-strict (чередовать роли)",
|
||||
"prompt_post_processing_strict": "Strict (чередовать роли, сначала пользователь)",
|
||||
"Select Horde models": "Выбрать модель из Horde",
|
||||
"Select Horde models": "Выберите модель из Horde",
|
||||
"Model ID (optional)": "Идентификатор модели (необязательно)",
|
||||
"Derive context size from backend": "Использовать бэкенд для определения размера контекста",
|
||||
"Rename current preset": "Переименовать пресет",
|
||||
"No Worlds active. Click here to select.": "Нет активных миров. Нажмите, чтобы выбрать.",
|
||||
"No Worlds active. Click here to select.": "Активных миров нет, ЛКМ для выбора.",
|
||||
"Title/Memo": "Название",
|
||||
"Strategy": "Статус",
|
||||
"Position": "Позиция",
|
||||
@ -2169,7 +2169,7 @@
|
||||
"instruct_derived": "Считывать из метаданных модели (по возможности)",
|
||||
"Confirm token parsing with": "Чтобы убедиться в правильности выделения токенов, используйте",
|
||||
"Reasoning Effort": "Рассуждения",
|
||||
"Constrains effort on reasoning for reasoning models.": "Регулирует объём внутренних рассуждений модели (reasoning), для моделей которые поддерживают эту возможность.\nНа данный момент поддерживаются три значения: Подробные, Обычные, Поверхностные.\nПри менее подробном рассуждении ответ получается быстрее, а также экономятся токены, уходящие на рассуждения.",
|
||||
"Constrains effort on reasoning for reasoning models.": "Регулирует объём внутренних рассуждений модели (reasoning), для моделей, которые поддерживают эту возможность.\nПри менее подробном рассуждении ответ получается быстрее, а также экономятся токены, уходящие на рассуждения.",
|
||||
"openai_reasoning_effort_low": "Поверхностные",
|
||||
"openai_reasoning_effort_medium": "Обычные",
|
||||
"openai_reasoning_effort_high": "Подробные",
|
||||
@ -2274,8 +2274,8 @@
|
||||
"Persona Name Not Set": "У персоны отсутствует имя",
|
||||
"You must bind a name to this persona before you can set a lorebook.": "Перед привязкой лорбука персоне необходимо присвоить имя.",
|
||||
"Default Persona Removed": "Персона по умолчанию снята",
|
||||
"Persona is locked to the current character": "Персона закреплена за этим персонажем",
|
||||
"Persona is locked to the current chat": "Персона закреплена за этим чатом",
|
||||
"Persona is locked to the current character": "Персона закреплена за текущим персонажем",
|
||||
"Persona is locked to the current chat": "Персона закреплена за текущим чатом",
|
||||
"characters": "перс.",
|
||||
"character": "персонаж",
|
||||
"in this group": "в группе",
|
||||
@ -2336,5 +2336,88 @@
|
||||
"Reasoning already exists.": "Рассуждения уже присутствуют.",
|
||||
"Edit Message": "Редактирование",
|
||||
"Status check bypassed": "Проверка статуса отключена",
|
||||
"Valid": "Работает"
|
||||
"Valid": "Работает",
|
||||
"Use Group Scoring": "Использовать Group Scoring",
|
||||
"Only the entries with the most number of key matches will be selected for Inclusion Group filtering": "До групповых фильтров будут допущены только записи с наибольшим кол-вом совпадений",
|
||||
"Can be used to automatically activate Quick Replies": "Используется для автоматической активации быстрых ответов (Quick Replies)",
|
||||
"( None )": "(Отсутствует)",
|
||||
"Tie this entry to specific characters or characters with specific tags": "Привязать запись к опред. персонажам или персонажам с заданными тегами",
|
||||
"Move Entry to Another Lorebook": "Переместить запись в другой лорбук",
|
||||
"There are no other lorebooks to move to.": "Некуда перемещать: не найдено других лорбуков.",
|
||||
"Select Target Lorebook": "Выберите куда переместить",
|
||||
"Move '${0}' to:": "Переместить '${0}' в:",
|
||||
"Please select a target lorebook.": "Выберите лорбук, в который будет перемещена запись.",
|
||||
"Scan depth cannot be negative": "Глубина сканирования не может быть отрицательной",
|
||||
"Scan depth cannot exceed ${0}": "Глубина сканирования не может превышать ${0}",
|
||||
"Select your current Reasoning Template": "Выберите текущий Шаблон рассуждений",
|
||||
"Delete template": "Удалить шаблон",
|
||||
"Reasoning Template": "Шаблон рассуждений",
|
||||
"openai_reasoning_effort_auto": "Авто",
|
||||
"openai_reasoning_effort_minimum": "Минимальные",
|
||||
"openai_reasoning_effort_maximum": "Максимальные",
|
||||
"OpenAI-style options: low, medium, high. Minimum and maximum are aliased to low and high. Auto does not send an effort level.": "OpenAI принимает следующее: low (Поверхностные), medium (Обычные), high (Подробные). Minimum (Минимальные) - то же самое, что low. Maximum (Максимальные) - то же самое, что high. При выборе Auto (Авто) значение не отсылается вообще.",
|
||||
"Allocates a portion of the response length for thinking (low: 10%, medium: 25%, high: 50%). Other options are model-dependent.": "Резервирует часть ответа для рассуждений (Поверхностные: 10% ответа, Обычные: 25%, Подробные: 50%). Остальные значения зависят от конкретной модели.",
|
||||
"xAI Model": "Модель xAI",
|
||||
"xAI API Key": "Ключ от API xAI",
|
||||
"HuggingFace Token": "Токен HuggingFace",
|
||||
"Endpoint URL": "Адрес эндпоинта",
|
||||
"Example: https://****.endpoints.huggingface.cloud": "Пример: https://****.endpoints.huggingface.cloud",
|
||||
"Featherless Model Selection": "Выбор модели из Featherless",
|
||||
"category": "категория",
|
||||
"Top": "Топовые",
|
||||
"All Classes": "Все классы",
|
||||
"Date Asc": "Дата, возрастание",
|
||||
"Date Desc": "Дата, убывание",
|
||||
"Background Image": "Фоновое изображение",
|
||||
"Delete the background?": "Удалить фон?",
|
||||
"Tags_as_Folders_desc": "Чтобы тег отображался как папка, его нужно отметить таковым в меню управления тегами. Нажмите сюда, чтобы открыть его.",
|
||||
"tag_entries": "раз исп.",
|
||||
"Multiple personas are connected to this character.\nSelect a persona to use for this chat.": "К этому персонажу привязано несколько персон.\nВыберите персону, которую хотите использовать в этом чате.",
|
||||
"Select Persona": "Выберите персону",
|
||||
"Completion Object": "Как часть Completion Object",
|
||||
"Move ${0} to:": "Переместить '${0}' в:",
|
||||
"Chat Scenario Override": "Перезапись сценария чата",
|
||||
"Unique to this chat.": "Действует только в рамках текущего чата.",
|
||||
"All group members will use the following scenario text instead of what is specified in their character cards.": "Все участники группы будут использовать этот сценарий вместо того, который указан в карточке.",
|
||||
"Checkpoints inherit the scenario override from their parent, and can be changed individually after that.": "Чекпоинты наследуют сценарий родителя, после отделения его можно менять.",
|
||||
"Delete Tag": "Удалить тег",
|
||||
"Do you want to delete the tag": "Вы точно хотите удалить тег",
|
||||
"If you want to merge all references to this tag into another tag, select it below:": "Если хотите заменить ссылки на этот тег на какой-то другой, то выберите из списка:",
|
||||
"Open Folder (Show all characters even if not selected)": "Открытая папка (показать всех персонажей, включая невыбранных)",
|
||||
"Closed Folder (Hide all characters unless selected)": "Закрытая папка (скрыть всех персонажей, кроме выбранных)",
|
||||
"No Folder": "Не папка",
|
||||
"Show only favorites": "Показать только избранных персонажей",
|
||||
"Show only groups": "Показать только группы",
|
||||
"Show only folders": "Показать только папки",
|
||||
"Manage tags": "Панель управления тегами",
|
||||
"Show Tag List": "Показать список тегов",
|
||||
"Clear all filters": "Сбросить все фильтры",
|
||||
"There are no items to display.": "Отображать абсолютно нечего.",
|
||||
"Characters and groups hidden by filters or closed folders": "Персонажи и группы скрыты настройками фильтров либо закрытыми папками",
|
||||
"Otterly empty": "Всё что можно, всё выдрано",
|
||||
"Here be dragons": "Список настолько очистился, что в него вернулись драконы",
|
||||
"Kiwibunga": "Настолько пусто, что киви прилетела посидеть",
|
||||
"Pump-a-Rum": "Пу-пу-пу",
|
||||
"Croak it": "Только кваканье лягушек и стрёкот сверчков",
|
||||
"${0} character hidden.": "Персонажей скрыто: ${0}.",
|
||||
"${0} characters hidden.": "Персонажей скрыто: ${0}.",
|
||||
"/ page": "/ стр.",
|
||||
"Context Length": "Размер контекста",
|
||||
"Added On": "Добавлена",
|
||||
"Class": "Класс",
|
||||
"Bulk_edit_characters": "Массовое редактирование персонажей\n\nЛКМ, чтобы выделить либо отменить выделение персонажа\nShift+ЛКМ, чтобы массово выделить либо отменить выделение персонажей\nПКМ, чтобы выбрать действие",
|
||||
"Bulk select all characters": "Выбрать всех персонажей",
|
||||
"Duplicate": "Клонировать",
|
||||
"Next page": "След. страница",
|
||||
"Previous page": "Пред. страница",
|
||||
"Group: ${0}": "Группа: ${0}",
|
||||
"You deleted a character/chat and arrived back here for safety reasons! Pick another character!": "Вы удалили персонажа или чат, и мы из соображений безопасности перенесли вас на эту страницу! Выберите другого персонажа!",
|
||||
"Group is empty.": "Группа пуста.",
|
||||
"No characters available": "Персонажей нет",
|
||||
"Choose what to export": "Выберите, что экспортировать",
|
||||
"Text Completion Preset": "Пресет для режима Text Completion",
|
||||
"Update enabled": "Обновить включенные",
|
||||
"Could not connect to API": "Не удалось подключиться к API",
|
||||
"Connected to API": "Соединение с API установлено",
|
||||
"Go back": "Назад"
|
||||
}
|
||||
|
@ -143,6 +143,7 @@ import {
|
||||
getHordeModels,
|
||||
adjustHordeGenerationParams,
|
||||
MIN_LENGTH,
|
||||
initHorde,
|
||||
} from './scripts/horde.js';
|
||||
|
||||
import {
|
||||
@ -175,6 +176,9 @@ import {
|
||||
saveBase64AsFile,
|
||||
uuidv4,
|
||||
equalsIgnoreCaseAndAccents,
|
||||
localizePagination,
|
||||
renderPaginationDropdown,
|
||||
paginationDropdownChangeHandler,
|
||||
} from './scripts/utils.js';
|
||||
import { debounce_timeout, IGNORE_SYMBOL } from './scripts/constants.js';
|
||||
|
||||
@ -994,6 +998,7 @@ async function firstLoadInit() {
|
||||
initAuthorsNote();
|
||||
await initPersonas();
|
||||
initWorldInfo();
|
||||
initHorde();
|
||||
initRossMods();
|
||||
initStats();
|
||||
initCfg();
|
||||
@ -1423,30 +1428,26 @@ function getBackBlock() {
|
||||
return template;
|
||||
}
|
||||
|
||||
function getEmptyBlock() {
|
||||
async function getEmptyBlock() {
|
||||
const icons = ['fa-dragon', 'fa-otter', 'fa-kiwi-bird', 'fa-crow', 'fa-frog'];
|
||||
const texts = ['Here be dragons', 'Otterly empty', 'Kiwibunga', 'Pump-a-Rum', 'Croak it'];
|
||||
const texts = [t`Here be dragons`, t`Otterly empty`, t`Kiwibunga`, t`Pump-a-Rum`, t`Croak it`];
|
||||
const roll = new Date().getMinutes() % icons.length;
|
||||
const emptyBlock = `
|
||||
<div class="text_block empty_block">
|
||||
<i class="fa-solid ${icons[roll]} fa-4x"></i>
|
||||
<h1>${texts[roll]}</h1>
|
||||
<p>There are no items to display.</p>
|
||||
</div>`;
|
||||
const params = {
|
||||
text: texts[roll],
|
||||
icon: icons[roll],
|
||||
};
|
||||
const emptyBlock = await renderTemplateAsync('emptyBlock', params);
|
||||
return $(emptyBlock);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {number} hidden Number of hidden characters
|
||||
*/
|
||||
function getHiddenBlock(hidden) {
|
||||
const hiddenBlock = `
|
||||
<div class="text_block hidden_block">
|
||||
<small>
|
||||
<p>${hidden} ${hidden > 1 ? 'characters' : 'character'} hidden.</p>
|
||||
<div class="fa-solid fa-circle-info opacity50p" data-i18n="[title]Characters and groups hidden by filters or closed folders" title="Characters and groups hidden by filters or closed folders"></div>
|
||||
</small>
|
||||
</div>`;
|
||||
async function getHiddenBlock(hidden) {
|
||||
const params = {
|
||||
text: (hidden > 1 ? t`${hidden} characters hidden.` : t`${hidden} character hidden.`),
|
||||
};
|
||||
const hiddenBlock = await renderTemplateAsync('hiddenBlock', params);
|
||||
return $(hiddenBlock);
|
||||
}
|
||||
|
||||
@ -1526,10 +1527,11 @@ export async function printCharacters(fullRefresh = false) {
|
||||
|
||||
const entities = getEntitiesList({ doFilter: true });
|
||||
|
||||
const pageSize = Number(accountStorage.getItem(storageKey)) || per_page_default;
|
||||
const sizeChangerOptions = [10, 25, 50, 100, 250, 500, 1000];
|
||||
$('#rm_print_characters_pagination').pagination({
|
||||
dataSource: entities,
|
||||
pageSize: Number(accountStorage.getItem(storageKey)) || per_page_default,
|
||||
sizeChangerOptions: [10, 25, 50, 100, 250, 500, 1000],
|
||||
pageSize,
|
||||
pageRange: 1,
|
||||
pageNumber: saveCharactersPage || 1,
|
||||
position: 'top',
|
||||
@ -1538,14 +1540,16 @@ export async function printCharacters(fullRefresh = false) {
|
||||
prevText: '<',
|
||||
nextText: '>',
|
||||
formatNavigator: PAGINATION_TEMPLATE,
|
||||
formatSizeChanger: renderPaginationDropdown(pageSize, sizeChangerOptions),
|
||||
showNavigator: true,
|
||||
callback: function (/** @type {Entity[]} */ data) {
|
||||
callback: async function (/** @type {Entity[]} */ data) {
|
||||
$(listId).empty();
|
||||
if (power_user.bogus_folders && isBogusFolderOpen()) {
|
||||
$(listId).append(getBackBlock());
|
||||
}
|
||||
if (!data.length) {
|
||||
$(listId).append(getEmptyBlock());
|
||||
const emptyBlock = await getEmptyBlock();
|
||||
$(listId).append(emptyBlock);
|
||||
}
|
||||
let displayCount = 0;
|
||||
for (const i of data) {
|
||||
@ -1566,13 +1570,16 @@ export async function printCharacters(fullRefresh = false) {
|
||||
|
||||
const hidden = (characters.length + groups.length) - displayCount;
|
||||
if (hidden > 0 && entitiesFilter.hasAnyFilter()) {
|
||||
$(listId).append(getHiddenBlock(hidden));
|
||||
const hiddenBlock = await getHiddenBlock(hidden);
|
||||
$(listId).append(hiddenBlock);
|
||||
}
|
||||
localizePagination($('#rm_print_characters_pagination'));
|
||||
|
||||
eventSource.emit(event_types.CHARACTER_PAGE_LOADED);
|
||||
},
|
||||
afterSizeSelectorChange: function (e) {
|
||||
afterSizeSelectorChange: function (e, size) {
|
||||
accountStorage.setItem(storageKey, e.target.value);
|
||||
paginationDropdownChangeHandler(e, size);
|
||||
},
|
||||
afterPaging: function (e) {
|
||||
saveCharactersPage = e;
|
||||
@ -8430,15 +8437,15 @@ export function callPopup(text, type, inputValue = '', { okButton, rows, wide, w
|
||||
function getOkButtonText() {
|
||||
if (['text', 'char_not_selected'].includes(popup_type)) {
|
||||
$dialoguePopupCancel.css('display', 'none');
|
||||
return okButton ?? 'Ok';
|
||||
return okButton ?? t`Ok`;
|
||||
} else if (['delete_extension'].includes(popup_type)) {
|
||||
return okButton ?? 'Ok';
|
||||
return okButton ?? t`Ok`;
|
||||
} else if (['new_chat', 'confirm'].includes(popup_type)) {
|
||||
return okButton ?? 'Yes';
|
||||
return okButton ?? t`Yes`;
|
||||
} else if (['input'].includes(popup_type)) {
|
||||
return okButton ?? t`Save`;
|
||||
}
|
||||
return okButton ?? 'Delete';
|
||||
return okButton ?? t`Delete`;
|
||||
}
|
||||
|
||||
dialogueCloseStop = true;
|
||||
|
@ -6,6 +6,7 @@ import { SlashCommand } from './slash-commands/SlashCommand.js';
|
||||
import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
|
||||
import { flashHighlight, stringFormat } from './utils.js';
|
||||
import { t } from './i18n.js';
|
||||
import { Popup } from './popup.js';
|
||||
|
||||
const BG_METADATA_KEY = 'custom_background';
|
||||
const LIST_METADATA_KEY = 'chat_backgrounds';
|
||||
@ -291,7 +292,7 @@ async function onDeleteBackgroundClick(e) {
|
||||
const bgToDelete = $(this).closest('.bg_example');
|
||||
const url = bgToDelete.data('url');
|
||||
const isCustom = bgToDelete.attr('custom') === 'true';
|
||||
const confirm = await callPopup('<h3>Delete the background?</h3>', 'confirm');
|
||||
const confirm = await Popup.show.confirm(t`Delete the background?`, null);
|
||||
const bg = bgToDelete.attr('bgfile');
|
||||
|
||||
if (confirm) {
|
||||
|
@ -13,6 +13,9 @@ import {
|
||||
getBase64Async,
|
||||
resetScrollHeight,
|
||||
initScrollHeight,
|
||||
localizePagination,
|
||||
renderPaginationDropdown,
|
||||
paginationDropdownChangeHandler,
|
||||
} from './utils.js';
|
||||
import { RA_CountCharTokens, humanizedDateTime, dragElement, favsToHotswap, getMessageTimeStamp } from './RossAscends-mods.js';
|
||||
import { power_user, loadMovingUIState, sortEntitiesList } from './power-user.js';
|
||||
@ -1374,6 +1377,8 @@ function getGroupCharacters({ doFilter, onlyMembers } = {}) {
|
||||
|
||||
function printGroupCandidates() {
|
||||
const storageKey = 'GroupCandidates_PerPage';
|
||||
const pageSize = Number(accountStorage.getItem(storageKey)) || 5;
|
||||
const sizeChangerOptions = [5, 10, 25, 50, 100, 200, 500, 1000];
|
||||
$('#rm_group_add_members_pagination').pagination({
|
||||
dataSource: getGroupCharacters({ doFilter: true, onlyMembers: false }),
|
||||
pageRange: 1,
|
||||
@ -1382,18 +1387,20 @@ function printGroupCandidates() {
|
||||
prevText: '<',
|
||||
nextText: '>',
|
||||
formatNavigator: PAGINATION_TEMPLATE,
|
||||
formatSizeChanger: renderPaginationDropdown(pageSize, sizeChangerOptions),
|
||||
showNavigator: true,
|
||||
showSizeChanger: true,
|
||||
pageSize: Number(accountStorage.getItem(storageKey)) || 5,
|
||||
sizeChangerOptions: [5, 10, 25, 50, 100, 200, 500, 1000],
|
||||
afterSizeSelectorChange: function (e) {
|
||||
pageSize,
|
||||
afterSizeSelectorChange: function (e, size) {
|
||||
accountStorage.setItem(storageKey, e.target.value);
|
||||
paginationDropdownChangeHandler(e, size);
|
||||
},
|
||||
callback: function (data) {
|
||||
$('#rm_group_add_members').empty();
|
||||
for (const i of data) {
|
||||
$('#rm_group_add_members').append(getGroupCharacterBlock(i.item));
|
||||
}
|
||||
localizePagination($('#rm_group_add_members_pagination'));
|
||||
},
|
||||
});
|
||||
}
|
||||
@ -1401,6 +1408,9 @@ function printGroupCandidates() {
|
||||
function printGroupMembers() {
|
||||
const storageKey = 'GroupMembers_PerPage';
|
||||
$('.rm_group_members_pagination').each(function () {
|
||||
let that = this;
|
||||
const pageSize = Number(accountStorage.getItem(storageKey)) || 5;
|
||||
const sizeChangerOptions = [5, 10, 25, 50, 100, 200, 500, 1000];
|
||||
$(this).pagination({
|
||||
dataSource: getGroupCharacters({ doFilter: false, onlyMembers: true }),
|
||||
pageRange: 1,
|
||||
@ -1411,16 +1421,18 @@ function printGroupMembers() {
|
||||
formatNavigator: PAGINATION_TEMPLATE,
|
||||
showNavigator: true,
|
||||
showSizeChanger: true,
|
||||
pageSize: Number(accountStorage.getItem(storageKey)) || 5,
|
||||
sizeChangerOptions: [5, 10, 25, 50, 100, 200, 500, 1000],
|
||||
afterSizeSelectorChange: function (e) {
|
||||
formatSizeChanger: renderPaginationDropdown(pageSize, sizeChangerOptions),
|
||||
pageSize,
|
||||
afterSizeSelectorChange: function (e, size) {
|
||||
accountStorage.setItem(storageKey, e.target.value);
|
||||
paginationDropdownChangeHandler(e, size);
|
||||
},
|
||||
callback: function (data) {
|
||||
$('.rm_group_members').empty();
|
||||
for (const i of data) {
|
||||
$('.rm_group_members').append(getGroupCharacterBlock(i.item));
|
||||
}
|
||||
localizePagination($(that));
|
||||
},
|
||||
});
|
||||
});
|
||||
@ -1804,7 +1816,7 @@ async function createGroup() {
|
||||
const memberNames = characters.filter(x => members.includes(x.avatar)).map(x => x.name).join(', ');
|
||||
|
||||
if (!name) {
|
||||
name = `Group: ${memberNames}`;
|
||||
name = t`Group: ${memberNames}`;
|
||||
}
|
||||
|
||||
const avatar_url = $('#group_avatar_preview img').attr('src');
|
||||
|
@ -394,7 +394,7 @@ function getHordeModelTemplate(option) {
|
||||
`));
|
||||
}
|
||||
|
||||
jQuery(function () {
|
||||
export function initHorde () {
|
||||
$('#horde_model').on('mousedown change', async function (e) {
|
||||
console.log('Horde model change', e);
|
||||
horde_settings.models = $('#horde_model').val();
|
||||
@ -441,7 +441,7 @@ jQuery(function () {
|
||||
if (!isMobile()) {
|
||||
$('#horde_model').select2({
|
||||
width: '100%',
|
||||
placeholder: 'Select Horde models',
|
||||
placeholder: t`Select Horde models`,
|
||||
allowClear: true,
|
||||
closeOnSelect: false,
|
||||
templateSelection: function (data) {
|
||||
@ -451,5 +451,5 @@ jQuery(function () {
|
||||
templateResult: getHordeModelTemplate,
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -3851,7 +3851,7 @@ function createLogitBiasListItem(entry) {
|
||||
}
|
||||
|
||||
async function createNewLogitBiasPreset() {
|
||||
const name = await callPopup('Preset name:', 'input');
|
||||
const name = await Popup.show.input(t`Preset name:`, null);
|
||||
|
||||
if (!name) {
|
||||
return;
|
||||
|
@ -22,7 +22,7 @@ import {
|
||||
} from '../script.js';
|
||||
import { persona_description_positions, power_user } from './power-user.js';
|
||||
import { getTokenCountAsync } from './tokenizers.js';
|
||||
import { PAGINATION_TEMPLATE, clearInfoBlock, debounce, delay, download, ensureImageFormatSupported, flashHighlight, getBase64Async, getCharIndex, isFalseBoolean, isTrueBoolean, onlyUnique, parseJsonFile, setInfoBlock } from './utils.js';
|
||||
import { PAGINATION_TEMPLATE, clearInfoBlock, debounce, delay, download, ensureImageFormatSupported, flashHighlight, getBase64Async, getCharIndex, isFalseBoolean, isTrueBoolean, onlyUnique, parseJsonFile, setInfoBlock, localizePagination, renderPaginationDropdown, paginationDropdownChangeHandler } from './utils.js';
|
||||
import { debounce_timeout } from './constants.js';
|
||||
import { FILTER_TYPES, FilterHelper } from './filters.js';
|
||||
import { groups, selected_group } from './group-chats.js';
|
||||
@ -250,16 +250,18 @@ export async function getUserAvatars(doRender = true, openPageAt = '') {
|
||||
const storageKey = 'Personas_PerPage';
|
||||
const listId = '#user_avatar_block';
|
||||
const perPage = Number(accountStorage.getItem(storageKey)) || 5;
|
||||
const sizeChangerOptions = [5, 10, 25, 50, 100, 250, 500, 1000];
|
||||
|
||||
$('#persona_pagination_container').pagination({
|
||||
dataSource: entities,
|
||||
pageSize: perPage,
|
||||
sizeChangerOptions: [5, 10, 25, 50, 100, 250, 500, 1000],
|
||||
sizeChangerOptions,
|
||||
pageRange: 1,
|
||||
pageNumber: savePersonasPage || 1,
|
||||
position: 'top',
|
||||
showPageNumbers: false,
|
||||
showSizeChanger: true,
|
||||
formatSizeChanger: renderPaginationDropdown(perPage, sizeChangerOptions),
|
||||
prevText: '<',
|
||||
nextText: '>',
|
||||
formatNavigator: PAGINATION_TEMPLATE,
|
||||
@ -270,9 +272,11 @@ export async function getUserAvatars(doRender = true, openPageAt = '') {
|
||||
$(listId).append(getUserAvatarBlock(item));
|
||||
}
|
||||
updatePersonaUIStates();
|
||||
localizePagination($('#persona_pagination_container'));
|
||||
},
|
||||
afterSizeSelectorChange: function (e) {
|
||||
afterSizeSelectorChange: function (e, size) {
|
||||
accountStorage.setItem(storageKey, e.target.value);
|
||||
paginationDropdownChangeHandler(e, size);
|
||||
},
|
||||
afterPaging: function (e) {
|
||||
savePersonasPage = e;
|
||||
|
@ -27,7 +27,7 @@ import { debounce_timeout } from './constants.js';
|
||||
import { INTERACTABLE_CONTROL_CLASS } from './keyboard.js';
|
||||
import { commonEnumProviders } from './slash-commands/SlashCommandCommonEnumsProvider.js';
|
||||
import { renderTemplateAsync } from './templates.js';
|
||||
import { t } from './i18n.js';
|
||||
import { t, translate } from './i18n.js';
|
||||
|
||||
export {
|
||||
TAG_FOLDER_TYPES,
|
||||
@ -318,7 +318,7 @@ function getTagBlock(tag, entities, hidden = 0, isUseless = false) {
|
||||
template.find('.avatar').css({ 'background-color': tag.color, 'color': tag.color2 }).attr('title', `[Folder] ${tag.name}`);
|
||||
template.find('.ch_name').text(tag.name).attr('title', `[Folder] ${tag.name}`);
|
||||
template.find('.bogus_folder_hidden_counter').text(hidden > 0 ? `${hidden} hidden` : '');
|
||||
template.find('.bogus_folder_counter').text(`${count} ${count != 1 ? 'characters' : 'character'}`);
|
||||
template.find('.bogus_folder_counter').text(`${count} ` + (count != 1 ? t`characters` : t`character`));
|
||||
template.find('.bogus_folder_icon').addClass(tagFolder.fa_icon);
|
||||
if (isUseless) template.addClass('useless');
|
||||
|
||||
@ -1057,7 +1057,7 @@ function appendTagToList(listElement, tag, { removable = false, isFilter = false
|
||||
tagElement.attr('title', tag.title);
|
||||
}
|
||||
if (tag.icon) {
|
||||
tagElement.find('.tag_name').text('').attr('title', `${tag.name} ${tag.title || ''}`.trim()).addClass(tag.icon);
|
||||
tagElement.find('.tag_name').text('').attr('title', `${translate(tag.name)} ${tag.title || ''}`.trim()).addClass(tag.icon);
|
||||
tagElement.addClass('actionable');
|
||||
}
|
||||
|
||||
@ -1644,6 +1644,7 @@ function updateDrawTagFolder(element, tag) {
|
||||
|
||||
// Draw/update css attributes for this class
|
||||
folderElement.attr('title', tagFolder.tooltip);
|
||||
folderElement.attr('data-i18n', '[title]' + tagFolder.tooltip);
|
||||
const indicator = folderElement.find('.tag_folder_indicator');
|
||||
indicator.text(tagFolder.icon);
|
||||
indicator.css('color', tagFolder.color);
|
||||
@ -1655,14 +1656,7 @@ async function onTagDeleteClick() {
|
||||
const tag = tags.find(x => x.id === id);
|
||||
const otherTags = sortTags(tags.filter(x => x.id !== id).map(x => ({ id: x.id, name: x.name })));
|
||||
|
||||
const popupContent = $(`
|
||||
<h3>Delete Tag</h3>
|
||||
<div>Do you want to delete the tag <div id="tag_to_delete" class="tags_inline inline-flex margin-r2"></div>?</div>
|
||||
<div class="m-t-2 marginBot5">If you want to merge all references to this tag into another tag, select it below:</div>
|
||||
<select id="merge_tag_select">
|
||||
<option value="">--- None ---</option>
|
||||
${otherTags.map(x => `<option value="${x.id}">${x.name}</option>`).join('')}
|
||||
</select>`);
|
||||
const popupContent = $(await renderTemplateAsync('deleteTag', { otherTags }));
|
||||
|
||||
appendTagToList(popupContent.find('#tag_to_delete'), tag);
|
||||
|
||||
|
9
public/scripts/templates/deleteTag.html
Normal file
9
public/scripts/templates/deleteTag.html
Normal file
@ -0,0 +1,9 @@
|
||||
<h3 data-i18n="Delete Tag">Delete Tag</h3>
|
||||
<div><span data-i18n="Do you want to delete the tag">Do you want to delete the tag</span> <div id="tag_to_delete" class="tags_inline inline-flex margin-r2"></div>?</div>
|
||||
<div class="m-t-2 marginBot5" data-i18n="If you want to merge all references to this tag into another tag, select it below:">If you want to merge all references to this tag into another tag, select it below:</div>
|
||||
<select id="merge_tag_select">
|
||||
<option value="">--- None ---</option>
|
||||
{{#each otherTags}}
|
||||
<option value="{{this.id}}">{{this.name}}</option>
|
||||
{{/each}}
|
||||
</select>
|
7
public/scripts/templates/emptyBlock.html
Normal file
7
public/scripts/templates/emptyBlock.html
Normal file
@ -0,0 +1,7 @@
|
||||
<div class="text_block empty_block">
|
||||
<i class="fa-solid {{icon}} fa-4x"></i>
|
||||
<h1>{{text}}</h1>
|
||||
<p data-i18n="There are no items to display.">
|
||||
There are no items to display.
|
||||
</p>
|
||||
</div>
|
6
public/scripts/templates/hiddenBlock.html
Normal file
6
public/scripts/templates/hiddenBlock.html
Normal file
@ -0,0 +1,6 @@
|
||||
<div class="text_block hidden_block">
|
||||
<small>
|
||||
<p>{{text}}</p>
|
||||
<div class="fa-solid fa-circle-info opacity50p" data-i18n="[title]Characters and groups hidden by filters or closed folders" title="Characters and groups hidden by filters or closed folders"></div>
|
||||
</small>
|
||||
</div>
|
@ -7,6 +7,7 @@ import { renderTemplateAsync } from './templates.js';
|
||||
import { POPUP_TYPE, callGenericPopup } from './popup.js';
|
||||
import { t } from './i18n.js';
|
||||
import { accountStorage } from './util/AccountStorage.js';
|
||||
import { localizePagination, PAGINATION_TEMPLATE } from './utils.js';
|
||||
|
||||
let mancerModels = [];
|
||||
let togetherModels = [];
|
||||
@ -361,9 +362,7 @@ export async function loadFeatherlessModels(data) {
|
||||
showSizeChanger: false,
|
||||
prevText: '<',
|
||||
nextText: '>',
|
||||
formatNavigator: function (currentPage, totalPage) {
|
||||
return (currentPage - 1) * perPage + 1 + ' - ' + currentPage * perPage + ' of ' + totalPage * perPage;
|
||||
},
|
||||
formatNavigator: PAGINATION_TEMPLATE,
|
||||
showNavigator: true,
|
||||
callback: function (modelsOnPage, pagination) {
|
||||
modelCardBlock.innerHTML = '';
|
||||
@ -385,15 +384,15 @@ export async function loadFeatherlessModels(data) {
|
||||
|
||||
const modelClassDiv = document.createElement('div');
|
||||
modelClassDiv.classList.add('model-class');
|
||||
modelClassDiv.textContent = `Class: ${model.model_class || 'N/A'}`;
|
||||
modelClassDiv.textContent = t`Class` + `: ${model.model_class || 'N/A'}`;
|
||||
|
||||
const contextLengthDiv = document.createElement('div');
|
||||
contextLengthDiv.classList.add('model-context-length');
|
||||
contextLengthDiv.textContent = `Context Length: ${model.context_length}`;
|
||||
contextLengthDiv.textContent = t`Context Length` + `: ${model.context_length}`;
|
||||
|
||||
const dateAddedDiv = document.createElement('div');
|
||||
dateAddedDiv.classList.add('model-date-added');
|
||||
dateAddedDiv.textContent = `Added On: ${new Date(model.created * 1000).toLocaleDateString()}`;
|
||||
dateAddedDiv.textContent = t`Added On` + `: ${new Date(model.created * 1000).toLocaleDateString()}`;
|
||||
|
||||
detailsContainer.appendChild(modelClassDiv);
|
||||
detailsContainer.appendChild(contextLengthDiv);
|
||||
@ -417,6 +416,7 @@ export async function loadFeatherlessModels(data) {
|
||||
|
||||
// Update the current page value whenever the page changes
|
||||
featherlessCurrentPage = pagination.pageNumber;
|
||||
localizePagination(paginationContainer);
|
||||
},
|
||||
afterSizeSelectorChange: function (e) {
|
||||
const newPerPage = e.target.value;
|
||||
|
@ -20,7 +20,46 @@ import { getCurrentLocale, t } from './i18n.js';
|
||||
* Pagination status string template.
|
||||
* @type {string}
|
||||
*/
|
||||
export const PAGINATION_TEMPLATE = '<%= rangeStart %>-<%= rangeEnd %> of <%= totalNumber %>';
|
||||
export const PAGINATION_TEMPLATE = '<%= rangeStart %>-<%= rangeEnd %> .. <%= totalNumber %>';
|
||||
|
||||
export const localizePagination = function(container) {
|
||||
container.find('[title="Next page"]').attr('title', t`Next page`);
|
||||
container.find('[title="Previous page"]').attr('title', t`Previous page`);
|
||||
};
|
||||
|
||||
/**
|
||||
* Renders a dropdown for selecting page size in pagination.
|
||||
* @param {number} pageSize Page size
|
||||
* @param {number[]} sizeChangerOptions Array of page size options
|
||||
* @returns {string} The rendered dropdown element as a string
|
||||
*/
|
||||
export const renderPaginationDropdown = function(pageSize, sizeChangerOptions) {
|
||||
const sizeSelect = document.createElement('select');
|
||||
sizeSelect.classList.add('J-paginationjs-size-select');
|
||||
|
||||
if (sizeChangerOptions.indexOf(pageSize) === -1) {
|
||||
sizeChangerOptions.unshift(pageSize);
|
||||
sizeChangerOptions.sort((a, b) => a - b);
|
||||
}
|
||||
|
||||
for (let i = 0; i < sizeChangerOptions.length; i++) {
|
||||
const option = document.createElement('option');
|
||||
option.value = `${sizeChangerOptions[i]}`;
|
||||
option.textContent = `${sizeChangerOptions[i]} ${t`/ page`}`;
|
||||
if (sizeChangerOptions[i] === pageSize) {
|
||||
option.setAttribute('selected', 'selected');
|
||||
}
|
||||
sizeSelect.appendChild(option);
|
||||
}
|
||||
|
||||
return sizeSelect.outerHTML;
|
||||
};
|
||||
|
||||
export const paginationDropdownChangeHandler = function(event, size) {
|
||||
let dropdown = $(event?.originalEvent?.currentTarget || event.delegateTarget).find('select');
|
||||
dropdown.find('[selected]').removeAttr('selected');
|
||||
dropdown.find(`[value=${size}]`).attr('selected', '');
|
||||
};
|
||||
|
||||
/**
|
||||
* Navigation options for pagination.
|
||||
|
@ -2658,7 +2658,7 @@ export async function getWorldEntry(name, data, entry) {
|
||||
if (!isMobile()) {
|
||||
$(characterFilter).select2({
|
||||
width: '100%',
|
||||
placeholder: 'Tie this entry to specific characters or characters with specific tags',
|
||||
placeholder: t`Tie this entry to specific characters or characters with specific tags`,
|
||||
allowClear: true,
|
||||
closeOnSelect: false,
|
||||
});
|
||||
@ -3258,7 +3258,7 @@ export async function getWorldEntry(name, data, entry) {
|
||||
|
||||
// Create wrapper div
|
||||
const wrapper = document.createElement('div');
|
||||
wrapper.textContent = t`Move "${sourceName}" to:`;
|
||||
wrapper.textContent = t`Move '${sourceName}' to:`;
|
||||
|
||||
// Create container and append elements
|
||||
const container = document.createElement('div');
|
||||
|
@ -5715,6 +5715,7 @@ body:not(.movingUI) .drawer-content.maximized {
|
||||
width: unset;
|
||||
margin: 0;
|
||||
font-size: calc(var(--mainFontSize) * 0.85);
|
||||
padding-right: 20px;
|
||||
}
|
||||
|
||||
.paginationjs-pages ul li a {
|
||||
|
Reference in New Issue
Block a user