diff --git a/public/index.html b/public/index.html index afed83cab..a0d5b4ef8 100644 --- a/public/index.html +++ b/public/index.html @@ -3178,9 +3178,10 @@
-
+
+ @@ -3289,9 +3290,10 @@
-
+
+ @@ -3469,9 +3471,10 @@
-
+
+ diff --git a/public/locales/ru-ru.json b/public/locales/ru-ru.json index a633db208..cd8068a98 100644 --- a/public/locales/ru-ru.json +++ b/public/locales/ru-ru.json @@ -1720,7 +1720,7 @@ "Proxy Preset": "Пресет для прокси", "Enter a name:": "Введите название:", "Are you sure you want to delete the selected profile?": "Вы точно хотите удалить выбранный профиль?", - "instruct_enabled": "Включить Instruct-режим", + "instruct_enabled": "Вкл/выкл Instruct-режим", "Instruct Template": "Шаблон Instruct-режима", "instruct_template_activation_regex_desc": "Автоматически активировать этот шаблон в момент подключения к API или выбора модели, если название модели соответствует этому рег. выражению.", "instruct_bind_to_context": "При включении этой опции Шаблон контекста будет выбираться, исходя из выбранного в текущий момент Шаблона Instruct-режима, либо по вашему желанию.", @@ -1730,11 +1730,11 @@ "Export Advanced Formatting settings": "Экспорт настроек Расширенного форматирования", "Select your current System Prompt": "Выберите текущий системный промпт", "Prompt Content": "Текст промпта", - "Update current prompt": "Обновить текущий промпт", + "Update current prompt": "Сохранить промпт", "Save prompt as": "Сохранить как...", "Import template": "Импорт шаблона", "Export template": "Экспорт шаблона", - "Restore current prompt": "Восстановить текущий промпт", + "Restore current prompt": "Восстановить промпт", "comma delimited,no spaces between": "через запятую,без пробелов в промежутках", "User Message Sequences": "Строки для сообщений пользователя", "Assistant Message Sequences": "Строки для сообщений ассистента", @@ -1757,7 +1757,7 @@ "Preset was not deleted from server": "Пресет не удалён с сервера", "Preset deleted": "Пресет удалён", "Delete the preset?": "Удалить пресет?", - "Preset updated": "Пресет обновлён", + "Preset updated": "Пресет сохранён", "Entered reverse proxy address is not a valid URL": "Введённый адрес прокси невалиден", "An error occurred while counting tokens: Token budget exceeded.": "Ошибка при подсчёте токенов: Превышен бюджет токенов", "An error occurred while counting tokens: Invalid character name": "Ошибка при подсчёте токенов: Невалидное имя персонажа", @@ -1893,5 +1893,71 @@ "Base": "Основание", "DRY_Base_desc": "Определяет, насколько быстро возрастает штраф с увеличением длины строки.", "Allowed Length": "Допустимая длина", - "DRY_Allowed_Length_desc": "Длина повторяющейся строки, при превышении которой DRY начинает налагать штраф." + "DRY_Allowed_Length_desc": "Длина повторяющейся строки, при превышении которой DRY начинает налагать штраф.", + "Invalid data provided for master import": "Глоб. импорт не может быть выполнен по причине невалидности данных", + "Importing instruct template...": "Импортируем...", + "Instruct template detected": "Обнаружен шаблон Instruct-режима", + "Importing as context template...": "Импортируем...", + "Context template detected": "Обнаружен шаблон контекста", + "Importing as system prompt...": "Импортируем...", + "System prompt detected": "Обнаружен системный промпт", + "Importing as settings preset...": "Импортируем...", + "Text Completion settings detected": "Обнаружены настройки Text Completion", + "No valid sections found in imported data": "Не найдено ни одной валидной секции данных", + "No sections selected for import": "Не выбрано ни одной секции для импорта", + "Import": "Импортировать", + "Imported ${0} settings: ${1}": "Импортировано ${0} настроек: ${1}", + "Export": "Экспортировать", + "No sections selected for export": "Не выбрано ни одной секции для экспорта", + "Cannot update GUI preset": "Пресет для GUI обновить невозможно", + "Template updated": "Шаблон сохранён", + "Hint: Use a character/group name to bind preset to a specific chat.": "Совет: введите имя персонажа/группы, чтобы привязать пресет к определённому чату.", + "Preset name:": "Название пресета:", + "Template name:": "Название шаблона:", + "Preset saved": "Пресет сохранён", + "Template saved": "Шаблон сохранён", + "Preset could not be saved": "Не удалось сохранить пресет", + "Preset could not be renamed": "Не удалось обновить пресет", + "Preset renamed": "Пресет переименован", + "Template renamed": "Шаблон переименован", + "Cannot delete GUI preset": "Пресет для GUI удалить невозможно", + "Failed to restore default preset": "Не удалось восстановить пресет по умолчанию", + "Failed to restore default template": "Не удалось восстановить шаблон по умолчанию", + "Rename preset": "Переименовать пресет", + "Rename template": "Переименовать шаблон", + "Enter a new name:": "Введите новое название:", + "Preset imported": "Пресет импортирован", + "Template imported": "Шаблон импортирован", + "Delete this preset?": "Удалить этот пресет?", + "Delete this template?": "Удалить этот шаблон?", + "This action is irreversible and your current settings will be overwritten.": "Отменить это действие невозможно. Ваши текущие настройки будут перезаписаны.", + "Preset deleted": "Пресет удалён", + "Template deleted": "Шаблон удалён", + "Template was not deleted from server": "Шаблон не удалён с сервера", + "Cannot restore GUI preset": "Пресет для Gui восстановить нельзя", + "Default preset cannot be restored": "Невозможно восстановить пресет по умолчанию", + "Default template cannot be restored": "Невозможно восстановить шаблон по умолчанию", + "Resetting a default preset will restore the default settings": "Сброс стандартного пресета восстановит настройки по умолчанию.", + "Resetting a default template will restore the default settings.": "Сброс стандартного шаблона восстановит настройки по умолчанию.", + "Are you sure?": "Вы уверены?", + "Default preset restored": "Стандартный пресет восстановлен", + "Default template restored": "Стандартный шаблон восстановлен", + "Resetting a custom preset will restore to the last saved state.": "Сброс пользовательского пресета откатит его к последнему сохранённому состоянию.", + "Resetting a custom template will restore to the last saved state.": "Сброс пользовательского шаблона откатит его к последнему сохранённому состоянию.", + "Preset restored": "Пресет восстановлен", + "Template restored": "Шаблон восстановлен", + "Update current template": "Сохранить шаблон", + "Rename current template": "Переименовать шаблон", + "Save template as": "Сохранить как...", + "Restore current template": "Восстановить шаблон", + "Delete the template": "Удалить шаблон", + "Rename current prompt": "Переименовать промпт", + "Select your current Context Template": "Выберите активный шаблон контекста", + "Select your current Instruct Template": "Выберите активный шаблон Instruct-режима", + "and connect to an": "и подключитесь к", + "You can add more": "Можете добавить больше", + "from other websites": "с других сайтов.", + "Go to the": "Загляните в", + "to install additional features.": ", чтобы установить разные дополнительные ресурсы.", + "or_welcome": "; также доступен" } diff --git a/public/script.js b/public/script.js index 8fc833666..cc3504b60 100644 --- a/public/script.js +++ b/public/script.js @@ -6755,7 +6755,7 @@ export async function saveSettings(type) { eventSource.emit(event_types.SETTINGS_UPDATED); }, error: function (jqXHR, exception) { - toastr.error(t`Check the server connection and reload the page to prevent data loss.t`, t`Settings could not be saved`); + toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Settings could not be saved`); console.log(exception); console.log(jqXHR); }, diff --git a/public/scripts/preset-manager.js b/public/scripts/preset-manager.js index 1fc993af4..e25de5eec 100644 --- a/public/scripts/preset-manager.js +++ b/public/scripts/preset-manager.js @@ -34,6 +34,7 @@ import { textgenerationwebui_settings as textgen_settings, } from './textgen-settings.js'; import { download, parseJsonFile, waitUntilCondition } from './utils.js'; +import { t } from './i18n.js'; const presetManagers = {}; @@ -194,32 +195,32 @@ class PresetManager { */ static async performMasterImport(data, fileName) { if (!data || typeof data !== 'object') { - toastr.error('Invalid data provided for master import'); + toastr.error(t`Invalid data provided for master import`); return; } // Check for legacy file imports // 1. Instruct Template if (this.isPossiblyInstructData(data)) { - toastr.info('Importing instruct template...', 'Instruct template detected'); + toastr.info(t`Importing instruct template...`, t`Instruct template detected`); return await getPresetManager('instruct').savePreset(data.name, data); } // 2. Context Template if (this.isPossiblyContextData(data)) { - toastr.info('Importing as context template...', 'Context template detected'); + toastr.info(t`Importing as context template...`, t`Context template detected`); return await getPresetManager('context').savePreset(data.name, data); } // 3. System Prompt if (this.isPossiblySystemPromptData(data)) { - toastr.info('Importing as system prompt...', 'System prompt detected'); + toastr.info(t`Importing as system prompt...`, t`System prompt detected`); return await getPresetManager('sysprompt').savePreset(data.name, data); } // 4. Text Completion settings if (this.isPossiblyTextCompletionData(data)) { - toastr.info('Importing as settings preset...', 'Text Completion settings detected'); + toastr.info(t`Importing as settings preset...`, t`Text Completion settings detected`); return await getPresetManager('textgenerationwebui').savePreset(fileName, data); } @@ -231,7 +232,7 @@ class PresetManager { } if (validSections.length === 0) { - toastr.error('No valid sections found in imported data'); + toastr.error(t`No valid sections found in imported data`); return; } @@ -242,8 +243,8 @@ class PresetManager { const html = $(await renderTemplateAsync('masterImport', { sections: sectionNames })); const popup = new Popup(html, POPUP_TYPE.CONFIRM, '', { - okButton: 'Import', - cancelButton: 'Cancel', + okButton: t`Import`, + cancelButton: t`Cancel`, }); const result = await popup.show(); @@ -257,7 +258,7 @@ class PresetManager { const confirmedSections = html.find('input:checked').map((_, el) => el instanceof HTMLInputElement && el.value).get(); if (confirmedSections.length === 0) { - toastr.info('No sections selected for import'); + toastr.info(t`No sections selected for import`); return; } @@ -270,7 +271,7 @@ class PresetManager { } } - toastr.success(`Imported ${importedSections.length} settings: ${importedSections.join(', ')}`); + toastr.success(t`Imported ${importedSections.length} settings: ${importedSections.join(', ')}`); } /** @@ -285,8 +286,8 @@ class PresetManager { const html = $(await renderTemplateAsync('masterExport', { sections: sectionNames })); const popup = new Popup(html, POPUP_TYPE.CONFIRM, '', { - okButton: 'Export', - cancelButton: 'Cancel', + okButton: t`Export`, + cancelButton: t`Cancel`, }); const result = await popup.show(); @@ -300,7 +301,7 @@ class PresetManager { const data = {}; if (confirmedSections.length === 0) { - toastr.info('No sections selected for export'); + toastr.info(t`No sections selected for export`); return; } @@ -328,7 +329,7 @@ class PresetManager { * @returns {any} Preset value */ findPreset(name) { - return $(this.select).find('option').filter(function() { + return $(this.select).find('option').filter(function () { return $(this).text() === name; }).val(); } @@ -354,7 +355,7 @@ class PresetManager { * @param {string} value Preset option value */ selectPreset(value) { - const option = $(this.select).filter(function() { + const option = $(this.select).filter(function () { return $(this).val() === value; }); option.prop('selected', true); @@ -366,21 +367,21 @@ class PresetManager { console.log(selected); if (selected.val() == 'gui') { - toastr.info('Cannot update GUI preset'); + toastr.info(t`Cannot update GUI preset`); return; } const name = selected.text(); await this.savePreset(name); - const successToast = !this.isAdvancedFormatting() ? 'Preset updated' : 'Template updated'; + const successToast = !this.isAdvancedFormatting() ? t`Preset updated` : t`Template updated`; toastr.success(successToast); } async savePresetAs() { const inputValue = this.getSelectedPresetName(); - const popupText = !this.isAdvancedFormatting() ? '

Hint: Use a character/group name to bind preset to a specific chat.

' : ''; - const headerText = !this.isAdvancedFormatting() ? 'Preset name:' : 'Template name:'; + const popupText = !this.isAdvancedFormatting() ? '

' + t`Hint: Use a character/group name to bind preset to a specific chat.` + '

' : ''; + const headerText = !this.isAdvancedFormatting() ? t`Preset name:` : t`Template name:`; const name = await Popup.show.input(headerText, popupText, inputValue); if (!name) { console.log('Preset name not provided'); @@ -389,7 +390,7 @@ class PresetManager { await this.savePreset(name); - const successToast = !this.isAdvancedFormatting() ? 'Preset saved' : 'Template saved'; + const successToast = !this.isAdvancedFormatting() ? t`Preset saved` : t`Template saved`; toastr.success(successToast); } @@ -411,7 +412,7 @@ class PresetManager { }); if (!response.ok) { - toastr.error('Check the server connection and reload the page to prevent data loss.', 'Preset could not be saved'); + toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Preset could not be saved`); console.error('Preset could not be saved', response); throw new Error('Preset could not be saved'); } @@ -422,6 +423,19 @@ class PresetManager { this.updateList(name, preset); } + async renamePreset(newName) { + const oldName = this.getSelectedPresetName(); + try { + await this.savePreset(newName); + await this.deletePreset(oldName); + } catch (error) { + toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Preset could not be renamed`); + console.error('Preset could not be renamed', error); + throw new Error('Preset could not be renamed'); + } + + } + getPresetList() { let presets = []; let preset_names = {}; @@ -585,13 +599,14 @@ class PresetManager { return settings; } - async deleteCurrentPreset() { + // pass no arguments to delete current preset + async deletePreset(name) { const { preset_names, presets } = this.getPresetList(); - const value = this.getSelectedPreset(); - const nameToDelete = this.getSelectedPresetName(); + const value = name ? (this.isKeyedApi() ? this.findPreset(name) : name) : this.getSelectedPreset(); + const nameToDelete = name || this.getSelectedPresetName(); if (value == 'gui') { - toastr.info('Cannot delete GUI preset'); + toastr.info(t`Cannot delete GUI preset`); return; } @@ -605,7 +620,10 @@ class PresetManager { delete preset_names[nameToDelete]; } - if (Object.keys(preset_names).length) { + // switch in UI only when deleting currently selected preset + const switchPresets = !name || this.getSelectedPresetName() == name; + + if (Object.keys(preset_names).length && switchPresets) { const nextPresetName = Object.keys(preset_names)[0]; const newValue = preset_names[nextPresetName]; $(this.select).find(`option[value="${newValue}"]`).attr('selected', 'true'); @@ -629,7 +647,7 @@ class PresetManager { }); if (!response.ok) { - const errorToast = !this.isAdvancedFormatting() ? 'Failed to restore default preset' : 'Failed to restore default template'; + const errorToast = !this.isAdvancedFormatting() ? t`Failed to restore default preset` : t`Failed to restore default template`; toastr.error(errorToast); return; } @@ -721,7 +739,8 @@ async function waitForConnection() { export async function initPresetManager() { eventSource.on(event_types.CHAT_CHANGED, autoSelectPreset); registerPresetManagers(); - SlashCommandParser.addCommandObject(SlashCommand.fromProps({ name: 'preset', + SlashCommandParser.addCommandObject(SlashCommand.fromProps({ + name: 'preset', callback: presetCommandCallback, returns: 'current preset', unnamedArgumentList: [ @@ -774,6 +793,29 @@ export async function initPresetManager() { await presetManager.savePresetAs(); }); + $(document).on('click', '[data-preset-manager-rename]', async function () { + const apiId = $(this).data('preset-manager-rename'); + const presetManager = getPresetManager(apiId); + + if (!presetManager) { + console.warn(`Preset Manager not found for API: ${apiId}`); + return; + } + + const popupHeader = !presetManager.isAdvancedFormatting() ? t`Rename preset` : t`Rename template`; + const oldName = presetManager.getSelectedPresetName(); + const newName = await Popup.show.input(popupHeader, t`Enter a new name:`, oldName); + if (!newName || oldName === newName) { + console.debug(!presetManager.isAdvancedFormatting() ? 'Preset rename cancelled' : 'Template rename cancelled'); + return; + } + + await presetManager.renamePreset(newName); + + const successToast = !presetManager.isAdvancedFormatting() ? t`Preset renamed` : t`Template renamed`; + toastr.success(successToast); + }); + $(document).on('click', '[data-preset-manager-export]', async function () { const apiId = $(this).data('preset-manager-export'); const presetManager = getPresetManager(apiId); @@ -816,7 +858,7 @@ export async function initPresetManager() { data['name'] = name; await presetManager.savePreset(name, data); - const successToast = !presetManager.isAdvancedFormatting() ? 'Preset imported' : 'Template imported'; + const successToast = !presetManager.isAdvancedFormatting() ? t`Preset imported` : t`Template imported`; toastr.success(successToast); e.target.value = null; }); @@ -830,19 +872,19 @@ export async function initPresetManager() { return; } - const headerText = !presetManager.isAdvancedFormatting() ? 'Delete this preset?' : 'Delete this template?'; - const confirm = await Popup.show.confirm(headerText, 'This action is irreversible and your current settings will be overwritten.'); + const headerText = !presetManager.isAdvancedFormatting() ? t`Delete this preset?` : t`Delete this template?`; + const confirm = await Popup.show.confirm(headerText, t`This action is irreversible and your current settings will be overwritten.`); if (!confirm) { return; } - const result = await presetManager.deleteCurrentPreset(); + const result = await presetManager.deletePreset(); if (result) { - const successToast = !presetManager.isAdvancedFormatting() ? 'Preset deleted' : 'Template deleted'; + const successToast = !presetManager.isAdvancedFormatting() ? t`Preset deleted` : t`Template deleted`; toastr.success(successToast); } else { - const warningToast = !presetManager.isAdvancedFormatting() ? 'Preset was not deleted from server' : 'Template was not deleted from server'; + const warningToast = !presetManager.isAdvancedFormatting() ? t`Preset was not deleted from server` : t`Template was not deleted from server`; toastr.warning(warningToast); } @@ -862,7 +904,7 @@ export async function initPresetManager() { const data = await presetManager.getDefaultPreset(name); if (name == 'gui') { - toastr.info('Cannot restore GUI preset'); + toastr.info(t`Cannot restore GUI preset`); return; } @@ -872,37 +914,37 @@ export async function initPresetManager() { if (data.isDefault) { if (Object.keys(data.preset).length === 0) { - const errorToast = !presetManager.isAdvancedFormatting() ? 'Default preset cannot be restored' : 'Default template cannot be restored'; + const errorToast = !presetManager.isAdvancedFormatting() ? t`Default preset cannot be restored` : t`Default template cannot be restored`; toastr.error(errorToast); return; } const confirmText = !presetManager.isAdvancedFormatting() - ? 'Resetting a default preset will restore the default settings.' - : 'Resetting a default template will restore the default settings.'; - const confirm = await Popup.show.confirm('Are you sure?', confirmText); + ? t`Resetting a default preset will restore the default settings.` + : t`Resetting a default template will restore the default settings.`; + const confirm = await Popup.show.confirm(t`Are you sure?`, confirmText); if (!confirm) { return; } - await presetManager.deleteCurrentPreset(); + await presetManager.deletePreset(); await presetManager.savePreset(name, data.preset); const option = presetManager.findPreset(name); presetManager.selectPreset(option); - const successToast = !presetManager.isAdvancedFormatting() ? 'Default preset restored' : 'Default template restored'; + const successToast = !presetManager.isAdvancedFormatting() ? t`Default preset restored` : t`Default template restored`; toastr.success(successToast); } else { const confirmText = !presetManager.isAdvancedFormatting() - ? 'Resetting a custom preset will restore to the last saved state.' - : 'Resetting a custom template will restore to the last saved state.'; - const confirm = await Popup.show.confirm('Are you sure?', confirmText); + ? t`Resetting a custom preset will restore to the last saved state.` + : t`Resetting a custom template will restore to the last saved state.`; + const confirm = await Popup.show.confirm(t`Are you sure?`, confirmText); if (!confirm) { return; } const option = presetManager.findPreset(name); presetManager.selectPreset(option); - const successToast = !presetManager.isAdvancedFormatting() ? 'Preset restored' : 'Template restored'; + const successToast = !presetManager.isAdvancedFormatting() ? t`Preset restored` : t`Template restored`; toastr.success(successToast); } }); diff --git a/public/scripts/templates/welcome.html b/public/scripts/templates/welcome.html index 202609012..931875ce5 100644 --- a/public/scripts/templates/welcome.html +++ b/public/scripts/templates/welcome.html @@ -10,7 +10,7 @@ Click and connect to an @@ -21,7 +21,7 @@ Click and pick a character. @@ -33,7 +33,7 @@ Sample characters - or + or to install additional features.