mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-06-05 21:59:27 +02:00
Work on translation
This commit is contained in:
@ -2278,7 +2278,7 @@
|
|||||||
<h4 data-i18n="Model Providers">Model Providers</h4>
|
<h4 data-i18n="Model Providers">Model Providers</h4>
|
||||||
<select id="openrouter_providers_text" class="openrouter_providers" multiple>
|
<select id="openrouter_providers_text" class="openrouter_providers" multiple>
|
||||||
</select>
|
</select>
|
||||||
<label class="checkbox_label" for="openrouter_allow_fallbacks_textgenerationwebui" title="Automatically chooses an alternative provider if chosen providers can't serve your request.">
|
<label class="checkbox_label" data-i18n="[title]Automatically chooses an alternative provider if chosen providers can't serve your request." for="openrouter_allow_fallbacks_textgenerationwebui" title="Automatically chooses an alternative provider if chosen providers can't serve your request.">
|
||||||
<input id="openrouter_allow_fallbacks_textgenerationwebui" type="checkbox" />
|
<input id="openrouter_allow_fallbacks_textgenerationwebui" type="checkbox" />
|
||||||
<span data-i18n="Allow fallback providers">Allow fallback providers</span>
|
<span data-i18n="Allow fallback providers">Allow fallback providers</span>
|
||||||
</label>
|
</label>
|
||||||
@ -2902,7 +2902,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<h4 data-i18n="Window AI Model">Window AI Model</h4>
|
<h4 data-i18n="Window AI Model">Window AI Model</h4>
|
||||||
<select id="model_windowai_select">
|
<select id="model_windowai_select">
|
||||||
<option value="">Use extension settings</option>
|
<option data-i18n="Use extension settings" value="">Use extension settings</option>
|
||||||
<option value="openai/gpt-3.5-turbo">openai/gpt-3.5-turbo</option>
|
<option value="openai/gpt-3.5-turbo">openai/gpt-3.5-turbo</option>
|
||||||
<option value="openai/gpt-3.5-turbo-16k">openai/gpt-3.5-turbo-16k</option>
|
<option value="openai/gpt-3.5-turbo-16k">openai/gpt-3.5-turbo-16k</option>
|
||||||
<option value="openai/gpt-4">openai/gpt-4</option>
|
<option value="openai/gpt-4">openai/gpt-4</option>
|
||||||
@ -2977,14 +2977,14 @@
|
|||||||
<h4 data-i18n="Model Providers">Model Providers</h4>
|
<h4 data-i18n="Model Providers">Model Providers</h4>
|
||||||
<select id="openrouter_providers_chat" class="openrouter_providers" multiple>
|
<select id="openrouter_providers_chat" class="openrouter_providers" multiple>
|
||||||
</select>
|
</select>
|
||||||
<label class="checkbox_label marginTopBot5" for="openrouter_allow_fallbacks" title="Automatically chooses an alternative provider if chosen providers can't serve your request.">
|
<label class="checkbox_label marginTopBot5" for="openrouter_allow_fallbacks" data-i18n="[title]Automatically chooses an alternative provider if chosen providers can't serve your request." title="Automatically chooses an alternative provider if chosen providers can't serve your request.">
|
||||||
<input id="openrouter_allow_fallbacks" type="checkbox" />
|
<input id="openrouter_allow_fallbacks" type="checkbox" />
|
||||||
<span data-i18n="Allow fallback providers">Allow fallback providers</span>
|
<span data-i18n="Allow fallback providers">Allow fallback providers</span>
|
||||||
</label>
|
</label>
|
||||||
</div>
|
</div>
|
||||||
<small class="marginTopBot5">
|
<small class="marginTopBot5">
|
||||||
<i class="fa-solid fa-lightbulb"></i>
|
<i class="fa-solid fa-lightbulb"></i>
|
||||||
<span>To use instruct formatting, switch to OpenRouter under Text Completion API.</span>
|
<span data-i18n="To use instruct formatting, switch to OpenRouter under Text Completion API.">To use instruct formatting, switch to OpenRouter under Text Completion API.</span>
|
||||||
</small>
|
</small>
|
||||||
</form>
|
</form>
|
||||||
<form id="scale_form" data-source="scale" action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
<form id="scale_form" data-source="scale" action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
||||||
@ -4601,7 +4601,7 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div nane="AutoContiueBlock" class="inline-drawer wide100p flexFlowColumn">
|
<div nane="AutoContiueBlock" class="inline-drawer wide100p flexFlowColumn">
|
||||||
<div class="inline-drawer-toggle inline-drawer-header userSettingsInnerExpandable" title="Automatically 'continue' a response if the model stopped before reaching a certain amount of tokens.">
|
<div class="inline-drawer-toggle inline-drawer-header userSettingsInnerExpandable" data-i18n="[title]Automatically 'continue' a response if the model stopped before reaching a certain amount of tokens." title="Automatically 'continue' a response if the model stopped before reaching a certain amount of tokens.">
|
||||||
<b><span data-i18n="Auto-Continue">Auto-Continue</span></b>
|
<b><span data-i18n="Auto-Continue">Auto-Continue</span></b>
|
||||||
<div class="fa-solid fa-circle-chevron-down inline-drawer-icon down"></div>
|
<div class="fa-solid fa-circle-chevron-down inline-drawer-icon down"></div>
|
||||||
</div>
|
</div>
|
||||||
@ -5734,7 +5734,7 @@
|
|||||||
<span class="drag-handle">☰</span>
|
<span class="drag-handle">☰</span>
|
||||||
<div class="gap5px world_entry_thin_controls wide100p alignitemscenter">
|
<div class="gap5px world_entry_thin_controls wide100p alignitemscenter">
|
||||||
<div class="inline-drawer-toggle fa-fw fa-solid fa-circle-chevron-down inline-drawer-icon down"></div>
|
<div class="inline-drawer-toggle fa-fw fa-solid fa-circle-chevron-down inline-drawer-icon down"></div>
|
||||||
<div class="fa-solid fa-toggle-on killSwitch" name="entryKillSwitch" title="Toggle entry's active state."></div>
|
<div class="fa-solid fa-toggle-on killSwitch" name="entryKillSwitch" data-i18n="[title]Toggle entry's active state." title="Toggle entry's active state."></div>
|
||||||
<div class="flex-container alignitemscenter wide100p">
|
<div class="flex-container alignitemscenter wide100p">
|
||||||
<div class="WIEntryTitleAndStatus flex-container flex1 alignitemscenter">
|
<div class="WIEntryTitleAndStatus flex-container flex1 alignitemscenter">
|
||||||
<div class="flex-container flex1">
|
<div class="flex-container flex1">
|
||||||
@ -5967,7 +5967,7 @@
|
|||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block-range">
|
<div class="range-block-range">
|
||||||
<input class="text_pole margin0" name="sticky" type="number" placeholder="Non-sticky" min="0" max="999999">
|
<input class="text_pole margin0" name="sticky" type="number" data-i18n="[placeholder]No-sticky" placeholder="Non-sticky" min="0" max="999999">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex2 flex-container flexFlowColumn flexNoGap" data-i18n="[title]Entries with a cooldown can't be activated N messages after being triggered." title="Entries with a cooldown can't be activated N messages after being triggered.">
|
<div class="flex2 flex-container flexFlowColumn flexNoGap" data-i18n="[title]Entries with a cooldown can't be activated N messages after being triggered." title="Entries with a cooldown can't be activated N messages after being triggered.">
|
||||||
@ -5980,7 +5980,7 @@
|
|||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block-range">
|
<div class="range-block-range">
|
||||||
<input class="text_pole margin0" name="cooldown" type="number" placeholder="No cooldown" min="0" max="999999">
|
<input class="text_pole margin0" name="cooldown" type="number" data-i18n="[placeholder]No cooldown" placeholder="No cooldown" min="0" max="999999">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex2 flex-container flexFlowColumn flexNoGap" data-i18n="[title]Entries with a delay can't be activated until there are N messages present in the chat." title="Entries with a delay can't be activated until there are N messages present in the chat.">
|
<div class="flex2 flex-container flexFlowColumn flexNoGap" data-i18n="[title]Entries with a delay can't be activated until there are N messages present in the chat." title="Entries with a delay can't be activated until there are N messages present in the chat.">
|
||||||
@ -5993,7 +5993,7 @@
|
|||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<div class="range-block-range">
|
<div class="range-block-range">
|
||||||
<input class="text_pole margin0" name="delay" type="number" placeholder="No delay" min="0" max="999999">
|
<input class="text_pole margin0" name="delay" type="number" data-i18n="[placeholder]No delay" placeholder="No delay" min="0" max="999999">
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -294,7 +294,7 @@
|
|||||||
"Avoid sending sensitive information to the Horde.": "Избегайте отправки личной информации Horde",
|
"Avoid sending sensitive information to the Horde.": "Избегайте отправки личной информации Horde",
|
||||||
"Review the Privacy statement": "Ознакомиться с заявлением о конфиденциальности",
|
"Review the Privacy statement": "Ознакомиться с заявлением о конфиденциальности",
|
||||||
"Trusted workers only": "Только доверенные рабочие машины",
|
"Trusted workers only": "Только доверенные рабочие машины",
|
||||||
"For privacy reasons, your API key will be hidden after you reload the page.": "По причинам безопасности ваш API-ключ будет скрыт после перезагрузки страницы.",
|
"For privacy reasons, your API key will be hidden after you reload the page.": "Из соображений безопасности ваш API-ключ будет скрыт после перезагрузки страницы.",
|
||||||
"-- Horde models not loaded --": "--Модель Horde не загружена--",
|
"-- Horde models not loaded --": "--Модель Horde не загружена--",
|
||||||
"Example: http://127.0.0.1:5000/api ": "Пример: http://127.0.0.1:5000/api",
|
"Example: http://127.0.0.1:5000/api ": "Пример: http://127.0.0.1:5000/api",
|
||||||
"No connection...": "Нет соединения...",
|
"No connection...": "Нет соединения...",
|
||||||
@ -331,7 +331,6 @@
|
|||||||
"UID ↘": "UID ↘",
|
"UID ↘": "UID ↘",
|
||||||
"Trigger% ↗": "Триггер% ↗",
|
"Trigger% ↗": "Триггер% ↗",
|
||||||
"Trigger% ↘": "Триггер% ↘",
|
"Trigger% ↘": "Триггер% ↘",
|
||||||
"Order:": "Порядок:",
|
|
||||||
"Depth:": "Глубина:",
|
"Depth:": "Глубина:",
|
||||||
"Character Lore First": "Сначала лор персонажа",
|
"Character Lore First": "Сначала лор персонажа",
|
||||||
"Global Lore First": "Сначала глобальный лор",
|
"Global Lore First": "Сначала глобальный лор",
|
||||||
@ -347,7 +346,7 @@
|
|||||||
"After Char Defs": "↓Перс.",
|
"After Char Defs": "↓Перс.",
|
||||||
"Before AN": "↑АЗ",
|
"Before AN": "↑АЗ",
|
||||||
"After AN": "↓АЗ",
|
"After AN": "↓АЗ",
|
||||||
"Order": "Порядок:",
|
"Order": "Очерёдность:",
|
||||||
"Update a theme file": "Обновить файл темы",
|
"Update a theme file": "Обновить файл темы",
|
||||||
"Save as a new theme": "Сохранить как новую тему",
|
"Save as a new theme": "Сохранить как новую тему",
|
||||||
"Minimum number of blacklisted words detected to trigger an auto-swipe": "Минимальное количество обнаруженных запрещённых слов, при котором срабатывает авто-свайп.",
|
"Minimum number of blacklisted words detected to trigger an auto-swipe": "Минимальное количество обнаруженных запрещённых слов, при котором срабатывает авто-свайп.",
|
||||||
@ -497,7 +496,7 @@
|
|||||||
"What this keyword should mean to the AI, sent verbatim": "Что это ключевое слово должно означать для ИИ, отправляется дословно",
|
"What this keyword should mean to the AI, sent verbatim": "Что это ключевое слово должно означать для ИИ, отправляется дословно",
|
||||||
"Filter to Character(s)": "Фильтр по персонажу(ам)",
|
"Filter to Character(s)": "Фильтр по персонажу(ам)",
|
||||||
"Character Exclusion": "Исключить персонажей",
|
"Character Exclusion": "Исключить персонажей",
|
||||||
"Inclusion Group": "Включить персонажей",
|
"Inclusion Group": "Группа записей",
|
||||||
"Only one entry with the same label will be activated": "Будет активна только одна запись с одинаковой меткой",
|
"Only one entry with the same label will be activated": "Будет активна только одна запись с одинаковой меткой",
|
||||||
"-- Characters not found --": "-- Персонажей не найдено --",
|
"-- Characters not found --": "-- Персонажей не найдено --",
|
||||||
"(This will be the first message from the character that starts every chat)": "(Это будет первое сообщение от персонажа, когда вы начинаете новый чат)",
|
"(This will be the first message from the character that starts every chat)": "(Это будет первое сообщение от персонажа, когда вы начинаете новый чат)",
|
||||||
@ -541,7 +540,7 @@
|
|||||||
"NOT ANY": "НЕ ЛЮБОЙ",
|
"NOT ANY": "НЕ ЛЮБОЙ",
|
||||||
"Optional Filter": "Дополнительный фильтр",
|
"Optional Filter": "Дополнительный фильтр",
|
||||||
"New Entry": "Новая запись",
|
"New Entry": "Новая запись",
|
||||||
"Fill empty Memo/Titles with Keywords": "Заполните пустые Заметки/Названия ключевыми словами",
|
"Fill empty Memo/Titles with Keywords": "Заполнить пустые названия ключевыми словами",
|
||||||
"AI Response Formatting": "Формат ответа ИИ",
|
"AI Response Formatting": "Формат ответа ИИ",
|
||||||
"Change Background Image": "Изменить фон",
|
"Change Background Image": "Изменить фон",
|
||||||
"Extensions": "Расширения",
|
"Extensions": "Расширения",
|
||||||
@ -628,7 +627,7 @@
|
|||||||
"UI Theme": "Тема UI",
|
"UI Theme": "Тема UI",
|
||||||
"This message is invisible for the AI": "Это сообщение невидимо для ИИ",
|
"This message is invisible for the AI": "Это сообщение невидимо для ИИ",
|
||||||
"Sampler Priority": "Приоритет сэмплеров",
|
"Sampler Priority": "Приоритет сэмплеров",
|
||||||
"Ooba only. Determines the order of samplers.": "Только Ooba. Определяет порядок сэмплеров.",
|
"Ooba only. Determines the order of samplers.": "Только oobabooga. Определяет порядок сэмплеров.",
|
||||||
"Load default order": "Загрузить стандартный порядок",
|
"Load default order": "Загрузить стандартный порядок",
|
||||||
"Max Tokens Second": "Макс. кол-во токенов в секунду",
|
"Max Tokens Second": "Макс. кол-во токенов в секунду",
|
||||||
"CFG": "CFG",
|
"CFG": "CFG",
|
||||||
@ -1342,7 +1341,7 @@
|
|||||||
"Chat Lorebook": "Chat Lorebook for",
|
"Chat Lorebook": "Chat Lorebook for",
|
||||||
"chat_world_template_txt": "A selected World Info will be bound to this chat. When generating an AI reply,\n it will be combined with the entries from global and character lorebooks.",
|
"chat_world_template_txt": "A selected World Info will be bound to this chat. When generating an AI reply,\n it will be combined with the entries from global and character lorebooks.",
|
||||||
"Use tag as folder": "Tag as folder",
|
"Use tag as folder": "Tag as folder",
|
||||||
"WI Entry Status:🔵 Constant🟢 Normal🔗 Vectorized❌ Disabled": "Статус записи:\n 🔵 Постоянная\n 🟢 Обычная\n 🔗 Векторизованная\n ❌ Отключена",
|
"WI Entry Status:🔵 Constant🟢 Normal🔗 Vectorized": "Статус записи:\n 🔵 Постоянная\n 🟢 Обычная\n 🔗 Векторизованная",
|
||||||
"WI_Entry_Status_Constant": "Постоянная",
|
"WI_Entry_Status_Constant": "Постоянная",
|
||||||
"WI_Entry_Status_Normal": "Обычная",
|
"WI_Entry_Status_Normal": "Обычная",
|
||||||
"WI_Entry_Status_Vectorized": "Векторизованная",
|
"WI_Entry_Status_Vectorized": "Векторизованная",
|
||||||
@ -1366,13 +1365,7 @@
|
|||||||
"Can be used to automatically activate Quick Replies": "Can be used to automatically activate Quick Replies",
|
"Can be used to automatically activate Quick Replies": "Can be used to automatically activate Quick Replies",
|
||||||
"Automation ID": "Automation ID",
|
"Automation ID": "Automation ID",
|
||||||
"( None )": "( None )",
|
"( None )": "( None )",
|
||||||
"Delay until recursion (this entry can only be activated on recursive checking)": "Delay until recursion (this entry can only be activated on recursive checking)",
|
|
||||||
"Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered.Documentation: World Info - Inclusion Group": "Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered.\rSupports multiple comma-separated groups.\r\rDocumentation: World Info - Inclusion Group",
|
|
||||||
"Prioritize this entry: When checked, this entry is prioritized out of all selections.If multiple are prioritized, the one with the highest 'Order' is chosen.": "Prioritize this entry: When checked, this entry is prioritized out of all selections.\rIf multiple are prioritized, the one with the highest 'Order' is chosen.\r",
|
|
||||||
"A relative likelihood of entry activation within the group": "A relative likelihood of entry activation within the group",
|
|
||||||
"Group Weight": "Group Weight",
|
|
||||||
"Add Memo": "Add Memo",
|
"Add Memo": "Add Memo",
|
||||||
"close": "close",
|
|
||||||
"reset": "reset",
|
"reset": "reset",
|
||||||
"save": "save",
|
"save": "save",
|
||||||
"Open checkpoint chat": "Открыть чат из чекпоинта",
|
"Open checkpoint chat": "Открыть чат из чекпоинта",
|
||||||
@ -2035,5 +2028,121 @@
|
|||||||
"tags_sorting_desc": "Автоматически сортировать теги по алфавиту после создания или переименования одного из них.\nПри выключении новые теги будут просто добавляться в конец.\n\nЕсли вручную перетащить один из тегов на другое место, автосортировка отключится.",
|
"tags_sorting_desc": "Автоматически сортировать теги по алфавиту после создания или переименования одного из них.\nПри выключении новые теги будут просто добавляться в конец.\n\nЕсли вручную перетащить один из тегов на другое место, автосортировка отключится.",
|
||||||
"Imported tags:": "Импортируемые теги:",
|
"Imported tags:": "Импортируемые теги:",
|
||||||
"Importing Tags": "Импорт тегов",
|
"Importing Tags": "Импорт тегов",
|
||||||
"Couldn't import tags:": "Не удалось импортировать теги:"
|
"Couldn't import tags:": "Не удалось импортировать теги:",
|
||||||
|
"Allow fallback models": "Разрешить fallback-модели",
|
||||||
|
"Allow fallback providers": "Разрешить fallback-провайдеров",
|
||||||
|
"To use instruct formatting, switch to OpenRouter under Text Completion API.": "Переключитесь на OpenRouter в Text Completion API, чтобы использовать форматирование Instruct-режима.",
|
||||||
|
"Select providers. No selection = all providers.": "Выберите провайдера. Нет выбранного = выбраны все.",
|
||||||
|
"Model Providers": "Провайдеры моделей",
|
||||||
|
"Select a model": "Выберите модель",
|
||||||
|
"Search models...": "Искать по моделям...",
|
||||||
|
"[Currently loaded]": "[Загруженная сейчас]",
|
||||||
|
"Search providers...": "Искать по провайдерам...",
|
||||||
|
"Automatically chooses an alternative provider if chosen providers can't serve your request.": "Автоматически переключаться на другого провайдера, если текущий не может обслужить запрос.",
|
||||||
|
"Example: 127.0.0.1:8000": "Пример: 127.0.0.1:8000",
|
||||||
|
"Edit a connection profile": "Редактировать профиль соединения",
|
||||||
|
"System Prompt Name": "Название системного промпта",
|
||||||
|
"Use System Prompt": "Использовать системный промпт",
|
||||||
|
"Hint:": "Подсказка:",
|
||||||
|
"Click on the setting name to omit it from the profile.": "Нажмите на название настройки, чтобы исключить её из профиля",
|
||||||
|
"Included settings:": "Сохранённые параметры:",
|
||||||
|
"Server URL": "Адрес сервера",
|
||||||
|
"NanoGPT API Key": "Ключ от API NanoGPT",
|
||||||
|
"NanoGPT Model": "Модель NanoGPT",
|
||||||
|
"Use extension settings": "Использовать настройки из расширения",
|
||||||
|
"DeepSeek API Key": "Ключ от API DeepSeek",
|
||||||
|
"DeepSeek Model": "Модель DeepSeek",
|
||||||
|
"prompt_post_processing_merge": "Объединять идущие подряд сообщения с одной ролью",
|
||||||
|
"prompt_post_processing_semi": "Semi-strict (чередовать роли)",
|
||||||
|
"prompt_post_processing_strict": "Strict (чередовать роли, сначала пользователь)",
|
||||||
|
"Select Horde models": "Выбрать модель из Horde",
|
||||||
|
"Model ID (optional)": "Идентификатор модели (необязательно)",
|
||||||
|
"Derive context size from backend": "Использовать бэкенд для определения размера контекста",
|
||||||
|
"Rename current preset": "Переименовать пресет",
|
||||||
|
"No Worlds active. Click here to select.": "Нет активных миров. Нажмите, чтобы выбрать.",
|
||||||
|
"Title/Memo": "Название",
|
||||||
|
"Strategy": "Статус",
|
||||||
|
"Position": "Позиция",
|
||||||
|
"Trigger %": "% срабатывания",
|
||||||
|
"Use global": "Глоб. настройка",
|
||||||
|
"Whole Words": "Целые слова",
|
||||||
|
"Non-recursable (will not be activated by another)": "Не рекурсивная (не активируется другими)",
|
||||||
|
"Delay until recursion (can only be activated on recursive checking)": "Рекурсивная (активируется только рекурсией)",
|
||||||
|
"Toggle entry's active state.": "Вкл/выкл запись.",
|
||||||
|
"Prioritize": "Важная",
|
||||||
|
"Prioritize this entry: When checked, this entry is prioritized out of all selections.If multiple are prioritized, the one with the highest 'Order' is chosen.": "Важная запись получает приоритет среди всех выбранных. Если важных записей несколько, выбирается та, у которой выше \"Очерёдность\".",
|
||||||
|
"Group Weight": "Вес в группе",
|
||||||
|
"A relative likelihood of entry activation within the group": "Относительная вероятность активации записи в рамках группы",
|
||||||
|
"Sticky": "Липучка",
|
||||||
|
"Sticky entries will stay active for N messages after being triggered.": "Запись-\"липучка\" останется активной в течение N сообщений после срабатывания.",
|
||||||
|
"Cooldown": "Кулдаун",
|
||||||
|
"Entries with a cooldown can't be activated N messages after being triggered.": "Запись с заданным кулдауном не активируется следующие N сообщений после срабатывания.",
|
||||||
|
"Delay": "Задержка",
|
||||||
|
"Entries with a delay can't be activated until there are N messages present in the chat.": "Запись с заданной задержкой может активироваться только после того, как в чате наберётся N сообщений.",
|
||||||
|
"No-sticky": "Нет",
|
||||||
|
"No cooldown": "Нет",
|
||||||
|
"No delay": "Нет",
|
||||||
|
"Filter to Characters or Tags": "Фильтровать по персонажам или тегам",
|
||||||
|
"Switch to plaintext mode": "Вкл/выкл режим чистого текста",
|
||||||
|
"Exclude": "Режим исключения",
|
||||||
|
"Switch the Character/Tags filter around to exclude the listed characters and tags from matching for this entry": "Инвертировать логику: для выбранных в фильтре персонажей/тегов данная запись активна НЕ БУДЕТ",
|
||||||
|
"Apply current sorting as Order": "Настроить Очерёдность в соответствии с текущей сортировкой",
|
||||||
|
"Create a new World Info": "Создать новый мир",
|
||||||
|
"Enter a name for the new file:": "Название нового файла:",
|
||||||
|
"Inclusion Groups ensure only one entry from a group is activated at a time, if multiple are triggered.Documentation: World Info - Inclusion Group": "Если сразу несколько записей из одной группы окажутся активированными, по факту сработает только одна. Одна запись может входить в несколько групп, отделяются запятыми. Раздел в документации: World Info - Inclusion Group",
|
||||||
|
"Valid World Info file name is required": "Требуется корректное имя для файла мира",
|
||||||
|
"World Info file has an invalid format": "Файл мира имеет неизвестный формат",
|
||||||
|
"World Info file has no entries": "В файле нет ни одной записи",
|
||||||
|
"Character not found.": "Персонаж не найден",
|
||||||
|
"Open a chat to get a name of the chat-bound lorebook": "Чтобы получить название привязанного к чату лорбука, требуется открыть чат.",
|
||||||
|
"File is not valid: ${0}": "Файл повреждён или имеет неизвестный формат: ${0}",
|
||||||
|
"The world with ${0} is invalid or corrupted.": "Мир ${0} повреждён или имеет неизвестный формат.",
|
||||||
|
"Deactivated all worlds": "Все миры отключены",
|
||||||
|
"No world found named: ${0}": "Не найдено мира с название ${0}",
|
||||||
|
"Activated world: ${0}": "Мир ${0} включён",
|
||||||
|
"Deactivated world: ${0}": "Мир ${0} отключён",
|
||||||
|
"World was not active: ${0}": "Мир ${0} не включён",
|
||||||
|
"The world '${0}' has been imported and linked to the character successfully.": "Мир ${0} успешно импортирован и привязан к персонажу.",
|
||||||
|
"World/Lorebook imported": "Мир/лорбук импортирован",
|
||||||
|
"Are you sure you want to import '${0}'?": "Вы точно хотите импортировать '${0}'?",
|
||||||
|
"It will overwrite the World/Lorebook with the same name.": "Существующий мир с таким же названием будет перезаписан.",
|
||||||
|
"Automatically 'continue' a response if the model stopped before reaching a certain amount of tokens.": "Автоматически \"продолжать\" ответ, если он оказался короче, чем целевая длина (в токенах).",
|
||||||
|
"None (not injected)": "Никуда",
|
||||||
|
"ext_sum_injection_position_none": "Пересказ не будет вставляться в промпт. Однако его по-прежнему можно будет вставить с помощью макроса {{summary}}",
|
||||||
|
"ext_sum_include_wi_scan": "Учитывать при сканировании лорбуком",
|
||||||
|
"ext_sum_include_wi_scan_desc": "Учитывать актуальный пересказ при сканировании промпта лорбуком.",
|
||||||
|
"ext_sum_force_tip": "Отправить запрос на создание пересказа прямо сейчас.",
|
||||||
|
"ext_sum_restore_tip": "Откатиться к предыдущему пересказу; используйте несколько раз, чтобы очистить историю пересказов для чата",
|
||||||
|
"Built-in Extensions:": "Комплектные расширения:",
|
||||||
|
"Installed Extensions:": "Установленные расширения:",
|
||||||
|
"Loading third-party extensions... Please wait...": "Загрузка сторонних расширений... Пожалуйста, подождите...",
|
||||||
|
"The page will be reloaded shortly...": "Страница будет перезагружена...",
|
||||||
|
"Extensions state changed": "Изменено состояние расширения",
|
||||||
|
"Error loading extensions. See browser console for details.": "Не удалось загрузить расширения. Подробности см. в консоли браузера.",
|
||||||
|
"You don't have permission to update global extensions.": "Отсутствуют права на обновление глобальных расширений.",
|
||||||
|
"Extension update failed": "Не удалось обновить расширение",
|
||||||
|
"Extension ${0} updated to ${1}": "Расширение ${0} обновлено до ${1}",
|
||||||
|
"Reload the page to apply updates": "Чтобы изменения вступили в силу, обновите страницу",
|
||||||
|
"You don't have permission to delete global extensions.": "Отсутствуют права на удаление глобальных расширений.",
|
||||||
|
"Are you sure you want to delete ${0}?": "Вы точно хотите удалить ${0}?",
|
||||||
|
"You don't have permission to move extensions.": "Отсутствуют права на перемещение расширений.",
|
||||||
|
"Are you sure you want to move ${0} to your local extensions? This will make it available only for you.": "Вы точно хотите сделать ${0} локальным расширением? После этого оно будет доступно только вам.",
|
||||||
|
"Are you sure you want to move ${0} to the global extensions? This will make it available for all users.": "Вы точно хотите сделать ${0} глобальным расширением? После этого оно будет доступно всем пользователям.",
|
||||||
|
"Extension ${0} moved.": "Расширение ${0} перемещено.",
|
||||||
|
"Extension ${0} deleted": "Расширение ${0} удалено.",
|
||||||
|
"Please wait...": "Пожалуйста, подождите...",
|
||||||
|
"Installing extension": "Идёт установка расширения",
|
||||||
|
"Extension installation failed": "Не удалось установить расширение",
|
||||||
|
"Extension '${0}' by ${1} (version ${2}) has been installed successfully!": "Расширение ${0} от автора ${1} (версия ${2}) успешно установлено!",
|
||||||
|
"Extension installation successful": "Расширение установлено",
|
||||||
|
"Extension updates available": "Доступных обновлений расширений",
|
||||||
|
"Auto-updating extensions. This may take several minutes.": "Запущено автоматическое обновление расширений. Это может занять несколько минут.",
|
||||||
|
"Install just for me": "Установить только мне",
|
||||||
|
"Install": "Установить",
|
||||||
|
"Install for all users": "Установить для всех пользователей",
|
||||||
|
"Modules provided by your Extras API:": "Модули из Extras API:",
|
||||||
|
"Not connected to the API!": "Нет соединения с API!",
|
||||||
|
"ext_type_system": "Это комплектное расширение. Его нельзя удалить, а обновляется оно вместе со всей системой.",
|
||||||
|
"Update all": "Обновить все",
|
||||||
|
"Close": "Закрыть"
|
||||||
}
|
}
|
||||||
|
@ -682,9 +682,9 @@ function getExtensionData(extension) {
|
|||||||
* @return {string} - The HTML string for the module information.
|
* @return {string} - The HTML string for the module information.
|
||||||
*/
|
*/
|
||||||
function getModuleInformation() {
|
function getModuleInformation() {
|
||||||
let moduleInfo = modules.length ? `<p>${DOMPurify.sanitize(modules.join(', '))}</p>` : '<p class="failure">Not connected to the API!</p>';
|
let moduleInfo = modules.length ? `<p>${DOMPurify.sanitize(modules.join(', '))}</p>` : '<p class="failure">' + t`Not connected to the API!` + '</p>';
|
||||||
return `
|
return `
|
||||||
<h3>Modules provided by your Extras API:</h3>
|
<h3>` + t`Modules provided by your Extras API:` + `</h3>
|
||||||
${moduleInfo}
|
${moduleInfo}
|
||||||
`;
|
`;
|
||||||
}
|
}
|
||||||
@ -703,11 +703,11 @@ async function showExtensionsDetails() {
|
|||||||
initialScrollTop = oldPopup.content.scrollTop;
|
initialScrollTop = oldPopup.content.scrollTop;
|
||||||
await oldPopup.completeCancelled();
|
await oldPopup.completeCancelled();
|
||||||
}
|
}
|
||||||
const htmlDefault = $('<div class="marginBot10"><h3 class="textAlignCenter">Built-in Extensions:</h3></div>');
|
const htmlDefault = $('<div class="marginBot10"><h3 class="textAlignCenter">' + t`Built-in Extensions:` + '</h3></div>');
|
||||||
const htmlExternal = $('<div class="marginBot10"><h3 class="textAlignCenter">Installed Extensions:</h3></div>');
|
const htmlExternal = $('<div class="marginBot10"><h3 class="textAlignCenter">' + t`Installed Extensions:` + '</h3></div>');
|
||||||
const htmlLoading = $(`<div class="flex-container alignItemsCenter justifyCenter marginTop10 marginBot5">
|
const htmlLoading = $(`<div class="flex-container alignItemsCenter justifyCenter marginTop10 marginBot5">
|
||||||
<i class="fa-solid fa-spinner fa-spin"></i>
|
<i class="fa-solid fa-spinner fa-spin"></i>
|
||||||
<span>Loading third-party extensions... Please wait...</span>
|
<span>` + t`Loading third-party extensions... Please wait...` + `</span>
|
||||||
</div>`);
|
</div>`);
|
||||||
|
|
||||||
htmlExternal.append(htmlLoading);
|
htmlExternal.append(htmlLoading);
|
||||||
@ -728,7 +728,7 @@ async function showExtensionsDetails() {
|
|||||||
|
|
||||||
/** @type {import('./popup.js').CustomPopupButton} */
|
/** @type {import('./popup.js').CustomPopupButton} */
|
||||||
const updateAllButton = {
|
const updateAllButton = {
|
||||||
text: 'Update all',
|
text: t`Update all`,
|
||||||
appendAtEnd: true,
|
appendAtEnd: true,
|
||||||
action: async () => {
|
action: async () => {
|
||||||
requiresReload = true;
|
requiresReload = true;
|
||||||
@ -740,7 +740,7 @@ async function showExtensionsDetails() {
|
|||||||
let waitingForSave = false;
|
let waitingForSave = false;
|
||||||
|
|
||||||
const popup = new Popup(html, POPUP_TYPE.TEXT, '', {
|
const popup = new Popup(html, POPUP_TYPE.TEXT, '', {
|
||||||
okButton: 'Close',
|
okButton: t`Close`,
|
||||||
wide: true,
|
wide: true,
|
||||||
large: true,
|
large: true,
|
||||||
customButtons: [updateAllButton],
|
customButtons: [updateAllButton],
|
||||||
@ -833,7 +833,7 @@ async function updateExtension(extensionName, quiet) {
|
|||||||
toastr.success('Extension is already up to date');
|
toastr.success('Extension is already up to date');
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
toastr.success(`Extension ${extensionName} updated to ${data.shortCommitHash}`, 'Reload the page to apply updates');
|
toastr.success(t`Extension ${extensionName} updated to ${data.shortCommitHash}`, t`Reload the page to apply updates`);
|
||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
console.error('Error:', error);
|
console.error('Error:', error);
|
||||||
@ -1001,7 +1001,7 @@ export async function installExtension(url, global) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const response = await request.json();
|
const response = await request.json();
|
||||||
toastr.success(`Extension "${response.display_name}" by ${response.author} (version ${response.version}) has been installed successfully!`, 'Extension installation successful');
|
toastr.success(t`Extension '${response.display_name}' by ${response.author} (version ${response.version}) has been installed successfully!`, t`Extension installation successful`);
|
||||||
console.debug(`Extension "${response.display_name}" has been installed successfully at ${response.extensionPath}`);
|
console.debug(`Extension "${response.display_name}" has been installed successfully at ${response.extensionPath}`);
|
||||||
await loadExtensionSettings({}, false, false);
|
await loadExtensionSettings({}, false, false);
|
||||||
await eventSource.emit(event_types.EXTENSION_SETTINGS_LOADED);
|
await eventSource.emit(event_types.EXTENSION_SETTINGS_LOADED);
|
||||||
@ -1175,7 +1175,7 @@ async function checkForExtensionUpdates(force) {
|
|||||||
await Promise.allSettled(promises);
|
await Promise.allSettled(promises);
|
||||||
|
|
||||||
if (updatesAvailable.length > 0) {
|
if (updatesAvailable.length > 0) {
|
||||||
toastr.info(`${updatesAvailable.map(x => `• ${x}`).join('\n')}`, 'Extension updates available');
|
toastr.info(`${updatesAvailable.map(x => `• ${x}`).join('\n')}`, t`Extension updates available`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1189,7 +1189,7 @@ async function autoUpdateExtensions(forceAll) {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const banner = toastr.info('Auto-updating extensions. This may take several minutes.', 'Please wait...', { timeOut: 10000, extendedTimeOut: 10000 });
|
const banner = toastr.info(t`Auto-updating extensions. This may take several minutes.`, t`Please wait...`, { timeOut: 10000, extendedTimeOut: 10000 });
|
||||||
const isCurrentUserAdmin = isAdmin();
|
const isCurrentUserAdmin = isAdmin();
|
||||||
const promises = [];
|
const promises = [];
|
||||||
for (const [id, manifest] of Object.entries(manifests)) {
|
for (const [id, manifest] of Object.entries(manifests)) {
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
<div>
|
<div>
|
||||||
<h3>Included settings:</h3>
|
<h3 data-i18n="Included settings:">Included settings:</h3>
|
||||||
<div class="justifyLeft flex-container flexFlowColumn flexNoGap">
|
<div class="justifyLeft flex-container flexFlowColumn flexNoGap">
|
||||||
{{#each settings}}
|
{{#each settings}}
|
||||||
<label class="checkbox_label">
|
<label class="checkbox_label">
|
||||||
<input type="checkbox" value="{{@key}}" name="exclude"{{#if this}} checked{{/if}}>
|
<input type="checkbox" value="{{@key}}" name="exclude"{{#if this}} checked{{/if}}>
|
||||||
<span>{{@key}}</span>
|
<span data-i18n="{{@key}}">{{@key}}</span>
|
||||||
</label>
|
</label>
|
||||||
{{/each}}
|
{{/each}}
|
||||||
</div>
|
</div>
|
||||||
|
@ -12,8 +12,8 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="marginTop5">
|
<div class="marginTop5">
|
||||||
<small>
|
<small>
|
||||||
<b>Hint:</b>
|
<b data-i18n="Hint:">Hint:</b>
|
||||||
<i>Click on the setting name to omit it from the profile.</i>
|
<i data-i18n="Click on the setting name to omit it from the profile.">Click on the setting name to omit it from the profile.</i>
|
||||||
</small>
|
</small>
|
||||||
</div>
|
</div>
|
||||||
<h3 data-i18n="Enter a name:">
|
<h3 data-i18n="Enter a name:">
|
||||||
|
@ -5491,8 +5491,8 @@ export function initOpenAI() {
|
|||||||
|
|
||||||
if (!isMobile()) {
|
if (!isMobile()) {
|
||||||
$('#model_openrouter_select').select2({
|
$('#model_openrouter_select').select2({
|
||||||
placeholder: 'Select a model',
|
placeholder: t`Select a model`,
|
||||||
searchInputPlaceholder: 'Search models...',
|
searchInputPlaceholder: t`Search models...`,
|
||||||
searchInputCssClass: 'text_pole',
|
searchInputCssClass: 'text_pole',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
templateResult: getOpenRouterModelTemplate,
|
templateResult: getOpenRouterModelTemplate,
|
||||||
|
@ -5,6 +5,7 @@ import { textgenerationwebui_settings as textgen_settings, textgen_types } from
|
|||||||
import { tokenizers } from './tokenizers.js';
|
import { tokenizers } from './tokenizers.js';
|
||||||
import { renderTemplateAsync } from './templates.js';
|
import { renderTemplateAsync } from './templates.js';
|
||||||
import { POPUP_TYPE, callGenericPopup } from './popup.js';
|
import { POPUP_TYPE, callGenericPopup } from './popup.js';
|
||||||
|
import { t } from './i18n.js';
|
||||||
|
|
||||||
let mancerModels = [];
|
let mancerModels = [];
|
||||||
let togetherModels = [];
|
let togetherModels = [];
|
||||||
@ -936,71 +937,71 @@ export function initTextGenModels() {
|
|||||||
|
|
||||||
if (!isMobile()) {
|
if (!isMobile()) {
|
||||||
$('#mancer_model').select2({
|
$('#mancer_model').select2({
|
||||||
placeholder: 'Select a model',
|
placeholder: t`Select a model`,
|
||||||
searchInputPlaceholder: 'Search models...',
|
searchInputPlaceholder: t`Search models...`,
|
||||||
searchInputCssClass: 'text_pole',
|
searchInputCssClass: 'text_pole',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
templateResult: getMancerModelTemplate,
|
templateResult: getMancerModelTemplate,
|
||||||
});
|
});
|
||||||
$('#model_togetherai_select').select2({
|
$('#model_togetherai_select').select2({
|
||||||
placeholder: 'Select a model',
|
placeholder: t`Select a model`,
|
||||||
searchInputPlaceholder: 'Search models...',
|
searchInputPlaceholder: t`Search models...`,
|
||||||
searchInputCssClass: 'text_pole',
|
searchInputCssClass: 'text_pole',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
templateResult: getTogetherModelTemplate,
|
templateResult: getTogetherModelTemplate,
|
||||||
});
|
});
|
||||||
$('#ollama_model').select2({
|
$('#ollama_model').select2({
|
||||||
placeholder: 'Select a model',
|
placeholder: t`Select a model`,
|
||||||
searchInputPlaceholder: 'Search models...',
|
searchInputPlaceholder: t`Search models...`,
|
||||||
searchInputCssClass: 'text_pole',
|
searchInputCssClass: 'text_pole',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
});
|
});
|
||||||
$('#tabby_model').select2({
|
$('#tabby_model').select2({
|
||||||
placeholder: '[Currently loaded]',
|
placeholder: t`[Currently loaded]`,
|
||||||
searchInputPlaceholder: 'Search models...',
|
searchInputPlaceholder: t`Search models...`,
|
||||||
searchInputCssClass: 'text_pole',
|
searchInputCssClass: 'text_pole',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
allowClear: true,
|
allowClear: true,
|
||||||
});
|
});
|
||||||
$('#model_infermaticai_select').select2({
|
$('#model_infermaticai_select').select2({
|
||||||
placeholder: 'Select a model',
|
placeholder: t`Select a model`,
|
||||||
searchInputPlaceholder: 'Search models...',
|
searchInputPlaceholder: t`Search models...`,
|
||||||
searchInputCssClass: 'text_pole',
|
searchInputCssClass: 'text_pole',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
templateResult: getInfermaticAIModelTemplate,
|
templateResult: getInfermaticAIModelTemplate,
|
||||||
});
|
});
|
||||||
$('#model_dreamgen_select').select2({
|
$('#model_dreamgen_select').select2({
|
||||||
placeholder: 'Select a model',
|
placeholder: t`Select a model`,
|
||||||
searchInputPlaceholder: 'Search models...',
|
searchInputPlaceholder: t`Search models...`,
|
||||||
searchInputCssClass: 'text_pole',
|
searchInputCssClass: 'text_pole',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
templateResult: getDreamGenModelTemplate,
|
templateResult: getDreamGenModelTemplate,
|
||||||
});
|
});
|
||||||
$('#openrouter_model').select2({
|
$('#openrouter_model').select2({
|
||||||
placeholder: 'Select a model',
|
placeholder: t`Select a model`,
|
||||||
searchInputPlaceholder: 'Search models...',
|
searchInputPlaceholder: t`Search models...`,
|
||||||
searchInputCssClass: 'text_pole',
|
searchInputCssClass: 'text_pole',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
templateResult: getOpenRouterModelTemplate,
|
templateResult: getOpenRouterModelTemplate,
|
||||||
});
|
});
|
||||||
$('#vllm_model').select2({
|
$('#vllm_model').select2({
|
||||||
placeholder: 'Select a model',
|
placeholder: t`Select a model`,
|
||||||
searchInputPlaceholder: 'Search models...',
|
searchInputPlaceholder: t`Search models...`,
|
||||||
searchInputCssClass: 'text_pole',
|
searchInputCssClass: 'text_pole',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
templateResult: getVllmModelTemplate,
|
templateResult: getVllmModelTemplate,
|
||||||
});
|
});
|
||||||
$('#aphrodite_model').select2({
|
$('#aphrodite_model').select2({
|
||||||
placeholder: 'Select a model',
|
placeholder: t`Select a model`,
|
||||||
searchInputPlaceholder: 'Search models...',
|
searchInputPlaceholder: t`Search models...`,
|
||||||
searchInputCssClass: 'text_pole',
|
searchInputCssClass: 'text_pole',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
templateResult: getAphroditeModelTemplate,
|
templateResult: getAphroditeModelTemplate,
|
||||||
});
|
});
|
||||||
providersSelect.select2({
|
providersSelect.select2({
|
||||||
sorter: data => data.sort((a, b) => a.text.localeCompare(b.text)),
|
sorter: data => data.sort((a, b) => a.text.localeCompare(b.text)),
|
||||||
placeholder: 'Select providers. No selection = all providers.',
|
placeholder: t`Select providers. No selection = all providers.`,
|
||||||
searchInputPlaceholder: 'Search providers...',
|
searchInputPlaceholder: t`Search providers...`,
|
||||||
searchInputCssClass: 'text_pole',
|
searchInputCssClass: 'text_pole',
|
||||||
width: '100%',
|
width: '100%',
|
||||||
closeOnSelect: false,
|
closeOnSelect: false,
|
||||||
|
@ -20,6 +20,7 @@ import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js';
|
|||||||
import { callGenericPopup, Popup, POPUP_TYPE } from './popup.js';
|
import { callGenericPopup, Popup, POPUP_TYPE } from './popup.js';
|
||||||
import { StructuredCloneMap } from './util/StructuredCloneMap.js';
|
import { StructuredCloneMap } from './util/StructuredCloneMap.js';
|
||||||
import { renderTemplateAsync } from './templates.js';
|
import { renderTemplateAsync } from './templates.js';
|
||||||
|
import { t } from './i18n.js';
|
||||||
|
|
||||||
export const world_info_insertion_strategy = {
|
export const world_info_insertion_strategy = {
|
||||||
evenly: 0,
|
evenly: 0,
|
||||||
@ -909,21 +910,21 @@ function registerWorldInfoSlashCommands() {
|
|||||||
|
|
||||||
async function getEntriesFromFile(file) {
|
async function getEntriesFromFile(file) {
|
||||||
if (!file || !world_names.includes(file)) {
|
if (!file || !world_names.includes(file)) {
|
||||||
toastr.warning('Valid World Info file name is required');
|
toastr.warning(t`Valid World Info file name is required`);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const data = await loadWorldInfo(file);
|
const data = await loadWorldInfo(file);
|
||||||
|
|
||||||
if (!data || !('entries' in data)) {
|
if (!data || !('entries' in data)) {
|
||||||
toastr.warning('World Info file has an invalid format');
|
toastr.warning(t`World Info file has an invalid format`);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
const entries = Object.values(data.entries);
|
const entries = Object.values(data.entries);
|
||||||
|
|
||||||
if (!entries || entries.length === 0) {
|
if (!entries || entries.length === 0) {
|
||||||
toastr.warning('World Info file has no entries');
|
toastr.warning(t`World Info file has no entries`);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -951,7 +952,7 @@ function registerWorldInfoSlashCommands() {
|
|||||||
name = String(name ?? '') || context.characters[context.characterId]?.avatar || null;
|
name = String(name ?? '') || context.characters[context.characterId]?.avatar || null;
|
||||||
const character = findChar({ name });
|
const character = findChar({ name });
|
||||||
if (!character) {
|
if (!character) {
|
||||||
toastr.error('Character not found.');
|
toastr.error(t`Character not found.`);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
const books = [];
|
const books = [];
|
||||||
@ -977,7 +978,7 @@ function registerWorldInfoSlashCommands() {
|
|||||||
const chatId = getCurrentChatId();
|
const chatId = getCurrentChatId();
|
||||||
|
|
||||||
if (!chatId) {
|
if (!chatId) {
|
||||||
toastr.warning('Open a chat to get a name of the chat-bound lorebook');
|
toastr.warning(t`Open a chat to get a name of the chat-bound lorebook`);
|
||||||
return '';
|
return '';
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4773,7 +4774,7 @@ export async function importEmbeddedWorldInfo(skipPopup = false) {
|
|||||||
const bookName = characters[chid]?.data?.character_book?.name || `${characters[chid]?.name}'s Lorebook`;
|
const bookName = characters[chid]?.data?.character_book?.name || `${characters[chid]?.name}'s Lorebook`;
|
||||||
|
|
||||||
if (!skipPopup) {
|
if (!skipPopup) {
|
||||||
const confirmation = await Popup.show.confirm(`Are you sure you want to import "${bookName}"?`, world_names.includes(bookName) ? 'It will overwrite the World/Lorebook with the same name.' : '');
|
const confirmation = await Popup.show.confirm(t`Are you sure you want to import '${bookName}'?`, world_names.includes(bookName) ? t`It will overwrite the World/Lorebook with the same name.` : '');
|
||||||
if (!confirmation) {
|
if (!confirmation) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -4785,7 +4786,7 @@ export async function importEmbeddedWorldInfo(skipPopup = false) {
|
|||||||
await updateWorldInfoList();
|
await updateWorldInfoList();
|
||||||
$('#character_world').val(bookName).trigger('change');
|
$('#character_world').val(bookName).trigger('change');
|
||||||
|
|
||||||
toastr.success(`The world "${bookName}" has been imported and linked to the character successfully.`, 'World/Lorebook imported');
|
toastr.success(t`The world '${bookName}' has been imported and linked to the character successfully.`, t`World/Lorebook imported`);
|
||||||
|
|
||||||
const newIndex = world_names.indexOf(bookName);
|
const newIndex = world_names.indexOf(bookName);
|
||||||
if (newIndex >= 0) {
|
if (newIndex >= 0) {
|
||||||
@ -4813,9 +4814,9 @@ export function onWorldInfoChange(args, text) {
|
|||||||
if (selected_world_info.includes(name)) {
|
if (selected_world_info.includes(name)) {
|
||||||
selected_world_info.splice(selected_world_info.indexOf(name), 1);
|
selected_world_info.splice(selected_world_info.indexOf(name), 1);
|
||||||
wiElement.prop('selected', false);
|
wiElement.prop('selected', false);
|
||||||
if (!silent) toastr.success(`Deactivated world: ${name}`);
|
if (!silent) toastr.success(t`Deactivated world: ${name}`);
|
||||||
} else {
|
} else {
|
||||||
if (!silent) toastr.error(`World was not active: ${name}`);
|
if (!silent) toastr.error(t`World was not active: ${name}`);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4823,11 +4824,11 @@ export function onWorldInfoChange(args, text) {
|
|||||||
if (selected_world_info.includes(name)) {
|
if (selected_world_info.includes(name)) {
|
||||||
selected_world_info.splice(selected_world_info.indexOf(name), 1);
|
selected_world_info.splice(selected_world_info.indexOf(name), 1);
|
||||||
wiElement.prop('selected', false);
|
wiElement.prop('selected', false);
|
||||||
if (!silent) toastr.success(`Deactivated world: ${name}`);
|
if (!silent) toastr.success(t`Deactivated world: ${name}`);
|
||||||
} else {
|
} else {
|
||||||
selected_world_info.push(name);
|
selected_world_info.push(name);
|
||||||
wiElement.prop('selected', true);
|
wiElement.prop('selected', true);
|
||||||
if (!silent) toastr.success(`Activated world: ${name}`);
|
if (!silent) toastr.success(t`Activated world: ${name}`);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -4835,16 +4836,16 @@ export function onWorldInfoChange(args, text) {
|
|||||||
default: {
|
default: {
|
||||||
selected_world_info.push(name);
|
selected_world_info.push(name);
|
||||||
wiElement.prop('selected', true);
|
wiElement.prop('selected', true);
|
||||||
if (!silent) toastr.success(`Activated world: ${name}`);
|
if (!silent) toastr.success(t`Activated world: ${name}`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (!silent) toastr.error(`No world found named: ${worldName}`);
|
if (!silent) toastr.error(t`No world found named: ${worldName}`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
$('#world_info').trigger('change');
|
$('#world_info').trigger('change');
|
||||||
} else { // if no args, unset all worlds
|
} else { // if no args, unset all worlds
|
||||||
if (!silent) toastr.success('Deactivated all worlds');
|
if (!silent) toastr.success(t`Deactivated all worlds`);
|
||||||
selected_world_info = [];
|
selected_world_info = [];
|
||||||
$('#world_info').val(null).trigger('change');
|
$('#world_info').val(null).trigger('change');
|
||||||
}
|
}
|
||||||
@ -4860,7 +4861,7 @@ export function onWorldInfoChange(args, text) {
|
|||||||
} else {
|
} else {
|
||||||
const wiElement = getWIElement(existingWorldName);
|
const wiElement = getWIElement(existingWorldName);
|
||||||
wiElement.prop('selected', false);
|
wiElement.prop('selected', false);
|
||||||
toastr.error(`The world with ${existingWorldName} is invalid or corrupted.`);
|
toastr.error(t`The world with ${existingWorldName} is invalid or corrupted.`);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -4892,7 +4893,7 @@ export async function importWorldInfo(file) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (jsonData === undefined || jsonData === null) {
|
if (jsonData === undefined || jsonData === null) {
|
||||||
toastr.error(`File is not valid: ${file.name}`);
|
toastr.error(t`File is not valid: ${file.name}`);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -5038,7 +5039,7 @@ jQuery(() => {
|
|||||||
|
|
||||||
$('#world_create_button').on('click', async () => {
|
$('#world_create_button').on('click', async () => {
|
||||||
const tempName = getFreeWorldName();
|
const tempName = getFreeWorldName();
|
||||||
const finalName = await Popup.show.input('Create a new World Info', 'Enter a name for the new file:', tempName);
|
const finalName = await Popup.show.input(t`Create a new World Info`, t`Enter a name for the new file:`, tempName);
|
||||||
|
|
||||||
if (finalName) {
|
if (finalName) {
|
||||||
await createNewWorldInfo(finalName, { interactive: true });
|
await createNewWorldInfo(finalName, { interactive: true });
|
||||||
|
Reference in New Issue
Block a user