Merge pull request #2930 from Yokayo/staging

Work on translation
This commit is contained in:
Cohee 2024-10-05 20:03:53 +03:00 committed by GitHub
commit a09a60ef31
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
13 changed files with 296 additions and 146 deletions

View File

@ -56,7 +56,7 @@
"Rep. Pen. Slope": "Rep. Pen. Slope",
"Top K": "Top K",
"Top P": "Top P",
"Do Sample": "Сделать образец",
"Do Sample": "Включить сэмплинг",
"Add BOS Token": "Добавлять BOS-токен",
"Add the bos_token to the beginning of prompts. Disabling this can make the replies more creative": "Добавлять BOS-токен в начале промпта. Если выключить, ответы могут стать более креативными.",
"Ban EOS Token": "Запретить EOS-токен",
@ -451,8 +451,8 @@
"Creator's Notes": "Заметки создателя",
"A-Z": "A-Z",
"Z-A": "Z-A",
"Newest": "Новейшие",
"Oldest": "Старейшие",
"Newest": "Сначала новые",
"Oldest": "Сначала старые",
"Favorites": "Избранные",
"Recent": "Последние",
"Most chats": "Больше всего чатов",
@ -564,7 +564,7 @@
"Advanced Definition": "Расширенное описание",
"Character Lore": "Лор персонажа",
"Export and Download": "Экспортировать и скачать",
"Duplicate Character": "Дублировать персонажа",
"Duplicate Character": "Клонировать персонажа",
"Create Character": "Создать персонажа",
"Delete Character": "Удалить персонажа",
"View all tags": "Показать все тэги",
@ -1690,7 +1690,7 @@
"Delete Message": "Удалить сообщение",
"Delete Swipe": "Удалить свайп",
"Could not get a reply from API. Check your connection settings / API key and try again.": "Не удалось получить ответ от API. Проверьте настройки соединения и API-ключ и повторите попытку.",
"Connecting To Proxy": "Подключение к прокси",
"Connecting To Proxy": "Подключиться к прокси",
"Are you sure you want to connect to the following proxy URL?": "Вы точно хотите соединиться с прокси по этому адресу?",
"API connection successful!": "Соединение с API установлено!",
"Proxy Saved": "Прокси сохранена",
@ -1747,5 +1747,151 @@
"Markdown Hotkeys": "Горячие клавиши для разметки",
"markdown_hotkeys_desc": "Включить горячие клавиши для вставки символов разметки в некоторых полях ввода. См. '/help hotkeys'.",
"Save and Update": "Сохранить и обновить",
"Profile name:": "Название профиля:"
"Profile name:": "Название профиля:",
"API returned an error": "API вернуло ошибку",
"Failed to save preset": "Не удалось сохранить пресет",
"Preset name should be unique.": "Название пресета должно быть уникальным.",
"Invalid file": "Невалидный файл",
"No preset selected": "Пресет не выбран",
"Invalid logit bias preset file.": "Файл пресета невалиден.",
"Preset was not deleted from server": "Пресет не удалён с сервера",
"Preset deleted": "Пресет удалён",
"Delete the preset?": "Удалить пресет?",
"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": "Ошибка при подсчёте токенов: Невалидное имя персонажа",
"Not enough free tokens for mandatory prompts. Raise your token Limit or disable custom prompts.": "Недостаточно токенов для всех выбранных промптов. Повысьте лимит токенов или отключите часть промптов.",
"The name of at least one character contained whitespaces or special characters. Please check your user and character name.": "В имени одного из персонажей содержится пробел или иной спецсимвол. Проверьте имена пользователя и персонажа.",
"An unknown error occurred while counting tokens. Further information may be available in console.": "Неизвестная ошибка при подсчёте токенов. Проверьте консоль, возможно, подробная информация есть там.",
"Encountered an error while processing your request.": "При обработке вашего запроса возникла ошибка.",
"Check you have credits available on your": "Убедитесь, что на вашем",
"OpenAI account quora_error": "аккаунте OpenAI",
"dot quota_error": "имеется достаточно кредитов.",
"If you have sufficient credits, please try again later.": "Если кредитов достаточно, то повторите попытку позднее.",
"Proxy preset '${0}' not found": "Пресет '${0}' не найден",
"Window.ai returned an error": "Window.ai вернул ошибку",
"Get it here:": "Загрузите здесь:",
"Extension is not installed": "Расширение не установлено",
"Update or remove your reverse proxy settings.": "Измените или удалите ваши настройки прокси.",
"An error occurred while importing prompts. More info available in console.": "В процессе импорта произошла ошибка. Подробную информацию см. в консоли.",
"Could not import prompts. Export failed validation.": "Не удалось импортировать промпты. Не пройдена валидация при экспорте.",
"Prompt import complete.": "Импорт завершён.",
"Are you sure you want to delete this prompt?": "Вы точно хотите удалить этот промпт?",
"Existing prompts with the same ID will be overridden. Do you want to proceed?": "Имеющиеся промпты с совпадающими идентификаторами будут перезаписаны. Продолжить?",
"This will reset the prompt order for this character. You will not lose any prompts.": "Будет сброшен порядок промптов для этого персонажа. Сами промпты вы не потеряете.",
"Note:": "Примечание:",
"this chat is temporary and will be deleted as soon as you leave it.": "это временный чат, он будет удалён, как только вы из него выйдете.",
"help_hotkeys_20": "Горячие клавиши для разметки",
"help_hotkeys_21": "Работают в окне ввода чата, а также в полях, отмеченных этим значком:",
"help_hotkeys_22": "**полужирный**",
"help_hotkeys_23": "*курсив*",
"help_hotkeys_24": "__подчёркивание__",
"help_hotkeys_25": "`inline-код`",
"help_hotkeys_26": "~~зачёркнутый~~",
"ext_regex_only_format_visual_desc": "Содержимое файла с историей чата останется нетронутым, изменения будут лишь визуальными (в UI).",
"Could not convert file": "Не удалось сконвертировать файл",
"Could not upload file": "Не удалось загрузить файл",
"Could not download file": "Не удалось скачать файл",
"File is too big. Maximum size is ${0}.": "Слишком большой файл. Максимальный размер: ${0}.",
"Binary files are not supported. Select a text file or image.": "Бинарные файлы не поддерживаются. Выберите текстовый файл или изображение.",
"No character or group selected": "Не выбрано ни одного персонажа или группы",
"Could not delete file": "Не удалось удалить файл",
"No attachments selected.": "Вложение не выбрано.",
"Data Bank": "Банк данных",
"No files were scraped.": "Скрапинг не выполнен.",
"Scraped ${0} files from ${1} to ${2}.": "Соскраплено из ${0} файлов из ${1} в ${2}.",
"Check browser console for details.": "Подробности см. в консоли браузера.",
"Scraping failed": "Ошибка скрапинга",
"External media has been blocked": "Внешние медиа отключены",
"Use the 'Ext. Media' button to allow it. Click on this message to dismiss.": "Разрешить можно с помощью кнопки 'Внешн. медиа'. Нажмите на это сообщение, чтобы его скрыть.",
"Couldn't get CSRF token. Please refresh the page.": "Не удалось получить CSRF токен. Попробуйте перезагрузить страницу.",
"Error": "Ошибка",
"API Error": "Ошибка API",
"Please wait until the chat is saved before switching characters.": "Пожалуйста, дождитесь сохранения чата, прежде чем переключать персонажа.",
"Your chat is still saving...": "Чат всё ещё сохраняется...",
"Character ${0} not found in the list": "Персонаж ${0} не найден в списке",
"Streaming is enabled, but the version of Kobold used does not support token streaming.": "Включён стриминг текста, но ваша версия Kobold не поддерживает стриминг токенов.",
"Streaming is not supported for the Legacy API. Update Ooba and use new API to enable streaming.": "Для устаревшего API стриминг недоступен. Обновите oobaboga и используйте новый API, чтобы включить стриминг.",
"Verify that the server is running and accessible.": "Убедитесь, что сервер запущен и доступен по сети.",
"ST Server cannot be reached": "Не удалось соединиться с сервером ST",
"You must first select a character to duplicate!": "Вы не выбрали персонажа, которого хотите клонировать!",
"Character Duplicated": "Персонаж склонирован",
"No character name provided.": "Вы не ввели имя персонажа.",
"Rename Character": "Переименование",
"No character selected.": "Вы не выбрали персонажа.",
"New name:": "Новое имя:",
"Same character name provided, so name did not change.": "Введено то же самое имя, ничего не изменилось.",
"Character renamed and past chats updated!": "Персонаж переименован, а чаты обновлены!",
"Character renamed!": "Персонаж переименован!",
"Something went wrong. The page will be reloaded.": "Что-то пошло не так. Страница будет перезагружена.",
"Past chat could not be updated: ${0}": "Не удалось обновить чат ${0}",
"Trying to save group chat with regular saveChat function. Aborting to prevent corruption.": "Произошла попытка сохранения группового чата функцией saveChat. Откатываем изменения, чтобы предотвратить потерю данных.",
"Check the server connection and reload the page to prevent data loss.": "Проверьте связь с сервером и перезагрузите страницу, чтобы избежать потери данных.",
"Chat could not be saved": "Не удалось сохранить чат",
"Settings could not be loaded after multiple attempts. Please try again later.": "Не удалось загрузить настройки за несколько попыток. Попробуйте позднее.",
"Settings could not be saved": "Не удалось сохранить настройки",
"Could not load chat data. Try reloading the page.": "Не удалось загрузить чат. Попробуйте обновить страницу.",
"Invalid process (no 'type')": "Невалидный процесс (нет параметра 'type')",
"Character Deleted: ${0}": "Персонаж удалён: ${0}",
"Character Created: ${0}": "Персонаж создан: ${0}",
"Group Created": "Группа создана",
"Group Deleted": "Группа удалена",
"Character Imported: ${0}": "Персонаж импортирован: ${0}",
"Invalid swipe ID: ${0}": "Некорректный идентификатор свайпа: ${0}",
"No messages to delete swipes from.": "Сообщение, из которого требуется удалить свайп, не найдено.",
"Can't delete the last swipe.": "Невозможно удалить единственный свайп.",
"GUI Settings preset is not supported for Horde. Please select another preset.": "Для Horde не поддерживаются пресеты настроек GUI. Пожалуйста, выберите другой пресет.",
"Embedded lorebook will be removed from this character.": "Встроенный лорбук будет удалён из персонажа.",
"Name is required": "Введите имя",
"Cannot create characters while generating. Stop the request and try again.": "Во время генерации ответа создать персонажа невозможно. Остановите запрос и повторите попытку.",
"Creation aborted": "Процесс создания прерван",
"Failed to create character": "Не удалось создать персонажа",
"Something went wrong while saving the character, or the image file provided was in an invalid format. Double check that the image is not a webp.": "Что-то пошло не так в процессе сохранения персонажа, либо вы загрузили файл некорректного формата. Проверьте, что изображение точно не в формате webp.",
"Context template '${0}' not found": "Шаблон контекста '${0}' не найден",
"Instruct template '${0}' not found": "Шаблон Instruct-режима '${0}' не найден",
"Error: ${0} is not a valid API": "Ошибка: ${0} не является валидным API",
"API set to ${0}, trying to connect..": "Установлено API ${0}, пробуем подключиться...",
"Unsupported file type: ": "Неподдерживаемый тип файла: ",
"Cannot import characters while generating. Stop the request and try again.": "Во время генерации ответа импорт персонажа невозможен. Остановите запрос и повторите попытку.",
"Import aborted": "Процесс импорта прерван",
"The file is likely invalid or corrupted.": "Вероятно, файл невалиден или повреждён.",
"Could not import character": "Не удалось импортировать персонажа",
"Cannot run /impersonate command while the reply is being generated.": "Во время генерации ответа выполнить /impersonate невозможно.",
"Name must be provided as an argument to rename this chat.": "Для переименования чата необходимо предоставить новое имя в качестве аргумента.",
"No chat selected that can be renamed.": "Чат, который требуется переименовать, не найден.",
"Successfully renamed chat to: ${0}": "Чат успешно переименован в: ${0}",
"Character ${0} not found. Skipping deletion.": "Персонаж ${0} не найден. Удаление пропускается.",
"Failed to delete character": "При удалении персонажа произошло ошибка",
"Are you sure you want to duplicate this character?": "Вы точно хотите клонировать этого персонажа?",
"If you just want to start a new chat with the same character...": "Если вы хотите просто создать новый чат, воспользуйтесь кнопкой \"Начать новый чат\" в меню слева внизу.",
"THIS IS PERMANENT!": "ОТМЕНИТЬ БУДЕТ НЕВОЗМОЖНО!",
"Also delete the chat files": "Также удалить файлы чатов",
"Delete the character?": "Удалить персонажа?",
"Not a valid number": "Некорректное число",
"Author's Note depth updated": "Глубина заметок автора обновлена",
"Author's Note frequency updated": "Частота заметок автора обновлена",
"Not a valid position": "Некорректная позиция",
"Author's Note position updated": "Позиция заметок автора обновлена",
"Something went wrong. Could not save character's author's note.": "Что-то пошло не так. Не удалось сохранить заметки автора для этого персонажа.",
"Select a character before trying to use Author's Note": "Сначала необходимо выбрать персонажа",
"Author's Note text updated": "Текст заметок автора обновлён",
"Group Validation": "Валидация группы",
"Warning: Listed member ${0} does not exist as a character. It will be removed from the group.": "Предупреждение: персонаж ${0} не существует в виде карточки. Он будет удалён из группы.",
"Group Chat could not be saved": "Не удалось сохранить групповой чат",
"Deleted group member swiped. To get a reply, add them back to the group.": "Вы пытаетесь свайпнуть удалённого члена группы. Чтобы получить ответ, добавьте этого персонажа обратно в группу.",
"Currently no group selected.": "В данный момент не выбрано ни одной группы.",
"Not so fast! Wait for the characters to stop typing before deleting the group.": "Чуть помедленнее! Перед удалением группы дождитесь, пока персонаж закончит печатать.",
"Delete the group?": "Удалить группу?",
"This will also delete all your chats with that group. If you want to delete a single conversation, select a \"View past chats\" option in the lower left menu.": "Вместе с ней будут удалены и все её чаты. Если требуется удалить только один чат, воспользуйтесь кнопкой \"Все чаты\" в меню в левом нижнем углу.",
"Can't peek a character while group reply is being generated": "Невозможно открыть карточку персонажа во время генерации ответа",
"Threshold": "Порог",
"DRY Repetition Penalty": "DRY Штраф за повтор",
"Multiplier": "Множитель",
"DRY_Multiplier_desc": "Поставьте в положение > 0, чтобы включить DRY. Определяет величину штрафа для кратчайшей \"штрафуемой\" строки.",
"DRY_Repetition_Penalty_desc": "DRY налагает штраф на токены, генерация которых приведёт к появлению строки, которая уже была в тексте раньше. Установите множитель = 0, чтобы отключить.",
"Base": "Основание",
"DRY_Base_desc": "Определяет, насколько быстро возрастает штраф с увеличением длины строки.",
"Allowed Length": "Допустимая длина",
"DRY_Allowed_Length_desc": "Длина повторяющейся строки, при превышении которой DRY начинает налагать штраф."
}

View File

@ -391,8 +391,8 @@ DOMPurify.addHook('uponSanitizeElement', (node, _, config) => {
if (localStorage.getItem(warningShownKey) === null) {
const warningToast = toastr.warning(
'Use the "Ext. Media" button to allow it. Click on this message to dismiss.',
'External media has been blocked',
t`Use the 'Ext. Media' button to allow it. Click on this message to dismiss.`,
t`External media has been blocked`,
{
timeOut: 0,
preventDuplicates: true,
@ -933,7 +933,7 @@ async function firstLoadInit() {
token = tokenData.token;
} catch {
hideLoader();
toastr.error('Couldn\'t get CSRF token. Please refresh the page.', 'Error', { timeOut: 0, extendedTimeOut: 0, preventDuplicates: true });
toastr.error(t`Couldn't get CSRF token. Please refresh the page.`, t`Error`, { timeOut: 0, extendedTimeOut: 0, preventDuplicates: true });
throw new Error('Initialization failed');
}
@ -1149,7 +1149,7 @@ async function getStatusKobold() {
// We didn't get a 200 status code, but the endpoint has an explanation. Which means it DID connect, but I digress.
if (online_status === 'no_connection' && data.response) {
toastr.error(data.response, 'API Error', { timeOut: 5000, preventDuplicates: true });
toastr.error(data.response, t`API Error`, { timeOut: 5000, preventDuplicates: true });
}
} catch (err) {
console.error('Error getting status', err);
@ -1235,7 +1235,7 @@ async function getStatusTextgen() {
// We didn't get a 200 status code, but the endpoint has an explanation. Which means it DID connect, but I digress.
if (online_status === 'no_connection' && data.response) {
toastr.error(data.response, 'API Error', { timeOut: 5000, preventDuplicates: true });
toastr.error(data.response, t`API Error`, { timeOut: 5000, preventDuplicates: true });
}
} catch (err) {
if (err instanceof AbortReason) {
@ -1287,7 +1287,7 @@ export async function selectCharacterById(id) {
}
if (isChatSaving) {
toastr.info('Please wait until the chat is saved before switching characters.', 'Your chat is still saving...');
toastr.info(t`Please wait until the chat is saved before switching characters.`, t`Your chat is still saving...`);
return;
}
@ -1641,7 +1641,7 @@ export async function getOneCharacter(avatarUrl) {
if (indexOf !== -1) {
characters[indexOf] = getData;
} else {
toastr.error(`Character ${avatarUrl} not found in the list`, 'Error', { timeOut: 5000, preventDuplicates: true });
toastr.error(t`Character ${avatarUrl} not found in the list`, t`Error`, { timeOut: 5000, preventDuplicates: true });
}
}
}
@ -3408,7 +3408,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
await eventSource.emit(event_types.GENERATION_AFTER_COMMANDS, type, { automatic_trigger, force_name2, quiet_prompt, quietToLoud, skipWIAN, force_chid, signal, quietImage }, dryRun);
if (main_api == 'kobold' && kai_settings.streaming_kobold && !kai_flags.can_use_streaming) {
toastr.error('Streaming is enabled, but the version of Kobold used does not support token streaming.', undefined, { timeOut: 10000, preventDuplicates: true });
toastr.error(t`Streaming is enabled, but the version of Kobold used does not support token streaming.`, undefined, { timeOut: 10000, preventDuplicates: true });
unblockGeneration(type);
return Promise.resolve();
}
@ -3417,7 +3417,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
textgen_settings.streaming &&
textgen_settings.legacy_api &&
textgen_settings.type === OOBA) {
toastr.error('Streaming is not supported for the Legacy API. Update Ooba and use new API to enable streaming.', undefined, { timeOut: 10000, preventDuplicates: true });
toastr.error(t`Streaming is not supported for the Legacy API. Update Ooba and use new API to enable streaming.`, undefined, { timeOut: 10000, preventDuplicates: true });
unblockGeneration(type);
return Promise.resolve();
}
@ -3433,7 +3433,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
if (!pingResult) {
unblockGeneration(type);
toastr.error('Verify that the server is running and accessible.', 'ST Server cannot be reached');
toastr.error(t`Verify that the server is running and accessible.`, t`ST Server cannot be reached`);
throw new Error('Server unreachable');
}
@ -4461,7 +4461,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
generatedPromptCache = '';
if (data?.response) {
toastr.error(data.response, 'API Error', { preventDuplicates: true });
toastr.error(data.response, t`API Error`, { preventDuplicates: true });
}
throw new Error(data?.response);
}
@ -4552,7 +4552,7 @@ export async function Generate(type, { automatic_trigger, force_name2, quiet_pro
function onError(exception) {
if (typeof exception?.error?.message === 'string') {
toastr.error(exception.error.message, 'Error', { timeOut: 10000, extendedTimeOut: 20000 });
toastr.error(exception.error.message, t`Error`, { timeOut: 10000, extendedTimeOut: 20000 });
}
generatedPromptCache = '';
@ -4956,7 +4956,7 @@ function addChatsSeparator(mesSendString) {
async function duplicateCharacter() {
if (!this_chid) {
toastr.warning('You must first select a character to duplicate!');
toastr.warning(t`You must first select a character to duplicate!`);
return '';
}
@ -4975,7 +4975,7 @@ async function duplicateCharacter() {
body: JSON.stringify(body),
});
if (response.ok) {
toastr.success('Character Duplicated');
toastr.success(t`Character Duplicated`);
const data = await response.json();
await eventSource.emit(event_types.CHARACTER_DUPLICATED, { oldAvatar: body.avatar_url, newAvatar: data.path });
await getCharacters();
@ -5822,23 +5822,23 @@ export function setSendButtonState(value) {
export async function renameCharacter(name = null, { silent = false, renameChats = null } = {}) {
if (!name && silent) {
toastr.warning('No character name provided.', 'Rename Character');
toastr.warning(t`No character name provided.`, t`Rename Character`);
return false;
}
if (this_chid === undefined) {
toastr.warning('No character selected.', 'Rename Character');
toastr.warning(t`No character selected.`, t`Rename Character`);
return false;
}
const oldAvatar = characters[this_chid].avatar;
const newValue = name || await callGenericPopup('<h3>New name:</h3>', POPUP_TYPE.INPUT, characters[this_chid].name);
const newValue = name || await callGenericPopup('<h3>' + t`New name:` + '</h3>', POPUP_TYPE.INPUT, characters[this_chid].name);
if (!newValue) {
toastr.warning('No character name provided.', 'Rename Character');
toastr.warning(t`No character name provided.`, t`Rename Character`);
return false;
}
if (newValue === characters[this_chid].name) {
toastr.info('Same character name provided, so name did not change.', 'Rename Character');
toastr.info(t`Same character name provided, so name did not change.`, t`Rename Character`);
return false;
}
@ -5885,9 +5885,9 @@ export async function renameCharacter(name = null, { silent = false, renameChats
if (renamePastChatsConfirm) {
await renamePastChats(newAvatar, newValue);
await reloadCurrentChat();
toastr.success('Character renamed and past chats updated!', 'Rename Character');
toastr.success(t`Character renamed and past chats updated!`, t`Rename Character`);
} else {
toastr.success('Character renamed!', 'Rename Character');
toastr.success(t`Character renamed!`, t`Rename Character`);
}
}
else {
@ -5900,8 +5900,8 @@ export async function renameCharacter(name = null, { silent = false, renameChats
}
catch (error) {
// Reloading to prevent data corruption
if (!silent) await callPopup('Something went wrong. The page will be reloaded.', 'text');
else toastr.error('Something went wrong. The page will be reloaded.', 'Rename Character');
if (!silent) await callPopup(t`Something went wrong. The page will be reloaded.`, 'text');
else toastr.error(t`Something went wrong. The page will be reloaded.`, t`Rename Character`);
console.log('Renaming character error:', error);
location.reload();
@ -5958,7 +5958,7 @@ async function renamePastChats(newAvatar, newValue) {
}
}
} catch (error) {
toastr.error(`Past chat could not be updated: ${file_name}`);
toastr.error(t`Past chat could not be updated: ${file_name}`);
console.error(error);
}
}
@ -6007,7 +6007,7 @@ export async function saveChat(chatName, withMetadata, mesId) {
characters[this_chid]['date_last_chat'] = Date.now();
chat.forEach(function (item, i) {
if (item['is_group']) {
toastr.error('Trying to save group chat with regular saveChat function. Aborting to prevent corruption.');
toastr.error(t`Trying to save group chat with regular saveChat function. Aborting to prevent corruption.`);
throw new Error('Group chat saved from saveChat');
}
/*
@ -6052,7 +6052,7 @@ export async function saveChat(chatName, withMetadata, mesId) {
contentType: 'application/json',
success: function (data) { },
error: function (jqXHR, exception) {
toastr.error('Check the server connection and reload the page to prevent data loss.', 'Chat could not be saved');
toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Chat could not be saved`);
console.log(exception);
console.log(jqXHR);
},
@ -6449,7 +6449,7 @@ export async function getSettings() {
if (!response.ok) {
reloadLoop();
toastr.error('Settings could not be loaded after multiple attempts. Please try again later.');
toastr.error(t`Settings could not be loaded after multiple attempts. Please try again later.`);
throw new Error('Error getting settings');
}
@ -6676,7 +6676,7 @@ export async function saveSettings(type) {
eventSource.emit(event_types.SETTINGS_UPDATED);
},
error: function (jqXHR, exception) {
toastr.error('Check the server connection and reload the page to prevent data loss.', 'Settings could not be saved');
toastr.error(t`Check the server connection and reload the page to prevent data loss.t`, t`Settings could not be saved`);
console.log(exception);
console.log(jqXHR);
},
@ -6942,7 +6942,7 @@ export async function displayPastChats() {
const data = await (selected_group ? getGroupPastChats(selected_group) : getPastCharacterChats());
if (!data) {
toastr.error('Could not load chat data. Try reloading the page.');
toastr.error(t`Could not load chat data. Try reloading the page.`);
return;
}
@ -7075,7 +7075,7 @@ export function selectRightMenuWithAnimation(selectedMenuId) {
export function select_rm_info(type, charId, previousCharId = null) {
if (!type) {
toastr.error('Invalid process (no \'type\')');
toastr.error(t`Invalid process (no 'type')`);
return;
}
if (type !== 'group_create') {
@ -7083,20 +7083,20 @@ export function select_rm_info(type, charId, previousCharId = null) {
}
if (type === 'char_delete') {
toastr.warning(`Character Deleted: ${displayName}`);
toastr.warning(t`Character Deleted: ${displayName}`);
}
if (type === 'char_create') {
toastr.success(`Character Created: ${displayName}`);
toastr.success(t`Character Created: ${displayName}`);
}
if (type === 'group_create') {
toastr.success('Group Created');
toastr.success(t`Group Created`);
}
if (type === 'group_delete') {
toastr.warning('Group Deleted');
toastr.warning(t`Group Deleted`);
}
if (type === 'char_import') {
toastr.success(`Character Imported: ${displayName}`);
toastr.success(t`Character Imported: ${displayName}`);
}
selectRightMenuWithAnimation('rm_characters_block');
@ -7554,25 +7554,25 @@ export function hideSwipeButtons() {
*/
export async function deleteSwipe(swipeId = null) {
if (swipeId && (isNaN(swipeId) || swipeId < 0)) {
toastr.warning(`Invalid swipe ID: ${swipeId + 1}`);
toastr.warning(t`Invalid swipe ID: ${swipeId + 1}`);
return;
}
const lastMessage = chat[chat.length - 1];
if (!lastMessage || !Array.isArray(lastMessage.swipes) || !lastMessage.swipes.length) {
toastr.warning('No messages to delete swipes from.');
toastr.warning(t`No messages to delete swipes from.`);
return;
}
if (lastMessage.swipes.length <= 1) {
toastr.warning('Can\'t delete the last swipe.');
toastr.warning(t`Can't delete the last swipe.`);
return;
}
swipeId = swipeId ?? lastMessage.swipe_id;
if (swipeId < 0 || swipeId >= lastMessage.swipes.length) {
toastr.warning(`Invalid swipe ID: ${swipeId + 1}`);
toastr.warning(t`Invalid swipe ID: ${swipeId + 1}`);
return;
}
@ -7711,7 +7711,7 @@ export function setGenerationProgress(progress) {
function isHordeGenerationNotAllowed() {
if (main_api == 'koboldhorde' && preset_settings == 'gui') {
toastr.error('GUI Settings preset is not supported for Horde. Please select another preset.');
toastr.error(t`GUI Settings preset is not supported for Horde. Please select another preset.`);
return true;
}
@ -7760,7 +7760,7 @@ function openCharacterWorldPopup() {
}
$('#character_json_data').val(JSON.stringify(data));
toastr.info('Embedded lorebook will be removed from this character.');
toastr.info(t`Embedded lorebook will be removed from this character.`);
} catch {
console.error('Failed to parse character JSON data.');
}
@ -7951,11 +7951,11 @@ async function createOrEditCharacter(e) {
if ($('#form_create').attr('actiontype') == 'createcharacter') {
if (String($('#character_name_pole').val()).length === 0) {
toastr.error('Name is required');
toastr.error(t`Name is required`);
return;
}
if (is_group_generating || is_send_press) {
toastr.error('Cannot create characters while generating. Stop the request and try again.', 'Creation aborted');
toastr.error(t`Cannot create characters while generating. Stop the request and try again.`, t`Creation aborted`);
return;
}
try {
@ -8039,7 +8039,7 @@ async function createOrEditCharacter(e) {
} catch (error) {
console.error('Error creating character', error);
toastr.error('Failed to create character');
toastr.error(t`Failed to create character`);
}
} else {
try {
@ -8098,7 +8098,7 @@ async function createOrEditCharacter(e) {
}
} catch (error) {
console.log(error);
toastr.error('Something went wrong while saving the character, or the image file provided was in an invalid format. Double check that the image is not a webp.');
toastr.error(t`Something went wrong while saving the character, or the image file provided was in an invalid format. Double check that the image is not a webp.`);
}
}
}
@ -8604,7 +8604,7 @@ async function selectContextCallback(args, name) {
const result = fuse.search(name);
if (result.length === 0) {
!quiet && toastr.warning(`Context template "${name}" not found`);
!quiet && toastr.warning(t`Context template '${name}' not found`);
return '';
}
@ -8624,7 +8624,7 @@ async function selectInstructCallback(args, name) {
const result = fuse.search(name);
if (result.length === 0) {
!quiet && toastr.warning(`Instruct template "${name}" not found`);
!quiet && toastr.warning(t`Instruct template '${name}' not found`);
return '';
}
@ -8676,7 +8676,7 @@ async function connectAPISlash(args, text) {
const apiConfig = CONNECT_API_MAP[text.toLowerCase()];
if (!apiConfig) {
toastr.error(`Error: ${text} is not a valid API`);
toastr.error(t`Error: ${text} is not a valid API`);
return '';
}
@ -8705,7 +8705,7 @@ async function connectAPISlash(args, text) {
}
const quiet = isTrueBoolean(args?.quiet);
const toast = quiet ? jQuery() : toastr.info(`API set to ${text}, trying to connect..`);
const toast = quiet ? jQuery() : toastr.info(t`API set to ${text}, trying to connect..`);
try {
await waitUntilCondition(() => online_status !== 'no_connection', 10000, 100);
@ -8744,7 +8744,7 @@ export async function processDroppedFiles(files, data = new Map()) {
const preservedName = data instanceof Map && data.get(file);
await importCharacter(file, preservedName);
} else {
toastr.warning('Unsupported file type: ' + file.name);
toastr.warning(t`Unsupported file type: ` + file.name);
}
}
}
@ -8757,7 +8757,7 @@ export async function processDroppedFiles(files, data = new Map()) {
*/
async function importCharacter(file, preserveFileName = '') {
if (is_group_generating || is_send_press) {
toastr.error('Cannot import characters while generating. Stop the request and try again.', 'Import aborted');
toastr.error(t`Cannot import characters while generating. Stop the request and try again.`, t`Import aborted`);
throw new Error('Cannot import character while generating');
}
@ -8784,7 +8784,7 @@ async function importCharacter(file, preserveFileName = '') {
});
if (data.error) {
toastr.error('The file is likely invalid or corrupted.', 'Could not import character');
toastr.error(t`The file is likely invalid or corrupted.`, t`Could not import character`);
return;
}
@ -8837,7 +8837,7 @@ async function doImpersonate(args, prompt) {
await waitUntilCondition(() => !is_send_press && !is_group_generating, 10000, 100);
} catch {
console.warn('Timeout waiting for generation unlock');
toastr.warning('Cannot run /impersonate command while the reply is being generated.');
toastr.warning(t`Cannot run /impersonate command while the reply is being generated.`);
return '';
}
@ -8899,19 +8899,19 @@ async function doDeleteChat() {
async function doRenameChat(_, chatName) {
if (!chatName) {
toastr.warning('Name must be provided as an argument to rename this chat.');
toastr.warning(t`Name must be provided as an argument to rename this chat.`);
return '';
}
const currentChatName = getCurrentChatId();
if (!currentChatName) {
toastr.warning('No chat selected that can be renamed.');
toastr.warning(t`No chat selected that can be renamed.`);
return '';
}
await renameChat(currentChatName, chatName);
toastr.success(`Successfully renamed chat to: ${chatName}`);
toastr.success(t`Successfully renamed chat to: ${chatName}`);
return '';
}
@ -9026,7 +9026,7 @@ export async function deleteCharacter(characterKey, { deleteChats = true } = {})
for (const key of characterKey) {
const character = characters.find(x => x.avatar == key);
if (!character) {
toastr.warning(`Character ${key} not found. Skipping deletion.`);
toastr.warning(t`Character ${key} not found. Skipping deletion.`);
continue;
}
@ -9043,7 +9043,7 @@ export async function deleteCharacter(characterKey, { deleteChats = true } = {})
});
if (!response.ok) {
toastr.error(`${response.status} ${response.statusText}`, 'Failed to delete character');
toastr.error(`${response.status} ${response.statusText}`, t`Failed to delete character`);
continue;
}
@ -9802,12 +9802,7 @@ jQuery(async function () {
let deleteChats = false;
const confirm = await Popup.show.confirm('Delete the character?', `
<b>THIS IS PERMANENT!<br><br>
<label for="del_char_checkbox" class="checkbox_label justifyCenter">
<input type="checkbox" id="del_char_checkbox" />
<small>Also delete the chat files</small>
</label></b>`, {
const confirm = await Popup.show.confirm(t`Delete the character?`, await renderTemplateAsync('deleteConfirm'), {
onClose: () => deleteChats = !!$('#del_char_checkbox').prop('checked'),
});
if (!confirm) {

View File

@ -8,6 +8,7 @@ import { debounce, waitUntilCondition, escapeHtml } from './utils.js';
import { debounce_timeout } from './constants.js';
import { renderTemplateAsync } from './templates.js';
import { Popup } from './popup.js';
import { t } from './i18n.js';
function debouncePromise(func, delay) {
let timeoutId;
@ -455,7 +456,7 @@ class PromptManager {
// Delete selected prompt from list form and close edit form
this.handleDeletePrompt = async (event) => {
Popup.show.confirm('Are you sure you want to delete this prompt?', null).then((userChoice) => {
Popup.show.confirm(t`Are you sure you want to delete this prompt?`, null).then((userChoice) => {
if (!userChoice) return;
const promptID = document.getElementById(this.configuration.prefix + 'prompt_manager_footer_append_prompt').value;
const prompt = this.getPromptById(promptID);
@ -531,7 +532,7 @@ class PromptManager {
// Import prompts for the selected character
this.handleImport = () => {
Popup.show.confirm('Existing prompts with the same ID will be overridden. Do you want to proceed?', null)
Popup.show.confirm(t`Existing prompts with the same ID will be overridden. Do you want to proceed?`, null)
.then(userChoice => {
if (!userChoice) return;
@ -552,7 +553,7 @@ class PromptManager {
const data = JSON.parse(fileContent);
this.import(data);
} catch (err) {
toastr.error('An error occurred while importing prompts. More info available in console.');
toastr.error(t`An error occurred while importing prompts. More info available in console.`);
console.log('An error occurred while importing prompts');
console.log(err.toString());
}
@ -567,7 +568,7 @@ class PromptManager {
// Restore default state of a characters prompt order
this.handleCharacterReset = () => {
Popup.show.confirm('This will reset the prompt order for this character. You will not lose any prompts.', null)
Popup.show.confirm(t`This will reset the prompt order for this character. You will not lose any prompts.`, null)
.then(userChoice => {
if (!userChoice) return;
@ -1649,7 +1650,7 @@ class PromptManager {
};
if (false === this.validateObject(controlObj, importData)) {
toastr.warning('Could not import prompts. Export failed validation.');
toastr.warning(t`Could not import prompts. Export failed validation.`);
return;
}
@ -1672,7 +1673,7 @@ class PromptManager {
throw new Error('Prompt order strategy not supported.');
}
toastr.success('Prompt import complete.');
toastr.success(t`Prompt import complete.`);
this.saveServiceSettings().then(() => this.render());
}

View File

@ -16,6 +16,7 @@ import { SlashCommandParser } from './slash-commands/SlashCommandParser.js';
import { SlashCommand } from './slash-commands/SlashCommand.js';
import { ARGUMENT_TYPE, SlashCommandArgument } from './slash-commands/SlashCommandArgument.js';
export { MODULE_NAME as NOTE_MODULE_NAME };
import { t } from './i18n.js';
const MODULE_NAME = '2_floating_prompt'; // <= Deliberate, for sorting lower than memory
@ -37,7 +38,7 @@ const chara_note_position = {
function setNoteTextCommand(_, text) {
$('#extension_floating_prompt').val(text).trigger('input');
toastr.success('Author\'s Note text updated');
toastr.success(t`Author's Note text updated`);
return '';
}
@ -45,12 +46,12 @@ function setNoteDepthCommand(_, text) {
const value = Number(text);
if (Number.isNaN(value)) {
toastr.error('Not a valid number');
toastr.error(t`Not a valid number`);
return;
}
$('#extension_floating_depth').val(Math.abs(value)).trigger('input');
toastr.success('Author\'s Note depth updated');
toastr.success(t`Author's Note depth updated`);
return '';
}
@ -58,12 +59,12 @@ function setNoteIntervalCommand(_, text) {
const value = Number(text);
if (Number.isNaN(value)) {
toastr.error('Not a valid number');
toastr.error(t`Not a valid number`);
return;
}
$('#extension_floating_interval').val(Math.abs(value)).trigger('input');
toastr.success('Author\'s Note frequency updated');
toastr.success(t`Author's Note frequency updated`);
return '';
}
@ -76,12 +77,12 @@ function setNotePositionCommand(_, text) {
const position = validPositions[text?.trim()];
if (Number.isNaN(position)) {
toastr.error('Not a valid position');
toastr.error(t`Not a valid position`);
return;
}
$(`input[name="extension_floating_position"][value="${position}"]`).prop('checked', true).trigger('input');
toastr.info('Author\'s Note position updated');
toastr.info(t`Author's Note position updated`);
return '';
}
@ -206,7 +207,7 @@ function onExtensionFloatingCharaPromptInput() {
extension_settings.note.chara.push(tempCharaNote);
} else {
console.log('Character author\'s note error: No avatar name key could be found.');
toastr.error('Something went wrong. Could not save character\'s author\'s note.');
toastr.error(t`Something went wrong. Could not save character's author's note.`);
// Don't save settings if something went wrong
return;
@ -397,7 +398,7 @@ function onANMenuItemClick() {
//because this listener takes priority
$('#options').stop().fadeOut(animation_duration);
} else {
toastr.warning('Select a character before trying to use Author\'s Note', '', { timeOut: 2000 });
toastr.warning(t`Select a character before trying to use Author's Note`, '', { timeOut: 2000 });
}
}

View File

@ -40,6 +40,7 @@ import { POPUP_RESULT, POPUP_TYPE, Popup, callGenericPopup } from './popup.js';
import { ScraperManager } from './scrapers.js';
import { DragAndDropHandler } from './dragdrop.js';
import { renderTemplateAsync } from './templates.js';
import { t } from './i18n.js';
/**
* @typedef {Object} FileAttachment
@ -206,7 +207,7 @@ export async function populateFileAttachment(message, inputId = 'file_form_input
const fileText = await converter(file);
base64Data = window.btoa(unescape(encodeURIComponent(fileText)));
} catch (error) {
toastr.error(String(error), 'Could not convert file');
toastr.error(String(error), t`Could not convert file`);
console.error('Could not convert file', error);
}
}
@ -257,7 +258,7 @@ export async function uploadFileAttachment(fileName, base64Data) {
const responseData = await result.json();
return responseData.path;
} catch (error) {
toastr.error(String(error), 'Could not upload file');
toastr.error(String(error), t`Could not upload file`);
console.error('Could not upload file', error);
}
}
@ -283,7 +284,7 @@ export async function getFileAttachment(url) {
const text = await result.text();
return text;
} catch (error) {
toastr.error(error, 'Could not download file');
toastr.error(error, t`Could not download file`);
console.error('Could not download file', error);
}
}
@ -299,13 +300,13 @@ async function validateFile(file) {
const isBinary = /^[\x00-\x08\x0E-\x1F\x7F-\xFF]*$/.test(fileText);
if (!isImage && file.size > fileSizeLimit) {
toastr.error(`File is too big. Maximum size is ${humanFileSize(fileSizeLimit)}.`);
toastr.error(t`File is too big. Maximum size is ${humanFileSize(fileSizeLimit)}.`);
return false;
}
// If file is binary
if (isBinary && !isImage && !isConvertible(file.type)) {
toastr.error('Binary files are not supported. Select a text file or image.');
toastr.error(t`Binary files are not supported. Select a text file or image.`);
return false;
}
@ -521,7 +522,7 @@ async function openExternalMediaOverridesDialog() {
const entityId = getCurrentEntityId();
if (!entityId) {
toastr.info('No character or group selected');
toastr.info(t`No character or group selected`);
return;
}
@ -646,7 +647,7 @@ async function deleteFileFromServer(url, silent = false) {
await eventSource.emit(event_types.FILE_ATTACHMENT_DELETED, url);
return true;
} catch (error) {
toastr.error(String(error), 'Could not delete file');
toastr.error(String(error), t`Could not delete file`);
console.error('Could not delete file', error);
return false;
}
@ -1054,7 +1055,7 @@ async function openAttachmentManager() {
const selectedAttachments = document.querySelectorAll('.attachmentListItemCheckboxContainer .attachmentListItemCheckbox:checked');
if (selectedAttachments.length === 0) {
toastr.info('No attachments selected.', 'Data Bank');
toastr.info(t`No attachments selected.`, t`Data Bank`);
return;
}
@ -1168,7 +1169,7 @@ async function runScraper(scraperId, target, callback) {
if (files.length === 0) {
console.warn('Scraping returned no files');
toastr.info('No files were scraped.', 'Data Bank');
toastr.info(t`No files were scraped.`, t`Data Bank`);
return;
}
@ -1176,12 +1177,12 @@ async function runScraper(scraperId, target, callback) {
await uploadFileAttachmentToServer(file, target);
}
toastr.success(`Scraped ${files.length} files from ${scraperId} to ${target}.`, 'Data Bank');
toastr.success(t`Scraped ${files.length} files from ${scraperId} to ${target}.`, t`Data Bank`);
callback();
}
catch (error) {
console.error('Scraping failed', error);
toastr.error('Check browser console for details.', 'Scraping failed');
toastr.error(t`Check browser console for details.`, t`Scraping failed`);
}
}
@ -1208,7 +1209,7 @@ export async function uploadFileAttachmentToServer(file, target) {
const fileText = await converter(file);
base64Data = window.btoa(unescape(encodeURIComponent(fileText)));
} catch (error) {
toastr.error(String(error), 'Could not convert file');
toastr.error(String(error), t`Could not convert file`);
console.error('Could not convert file', error);
}
} else {

View File

@ -132,7 +132,7 @@
<small data-i18n="ext_regex_other_options" data-i18n="Ephemerality">Ephemerality</small>
<span class="fa-solid fa-circle-question note-link-span" title="By default, regex scripts alter the chat file directly and irreversibly.&#13;Enabling either (or both) of the options below will prevent chat file alteration, while still altering the specified item(s)."></span>
</span>
<label class="checkbox flex-container" title="Chat history file contents won't change, but regex will be applied to the messages displayed in the Chat UI.">
<label class="checkbox flex-container" data-i18n="[title]ext_regex_only_format_visual_desc" title="Chat history file contents won't change, but regex will be applied to the messages displayed in the Chat UI.">
<input type="checkbox" name="only_format_display" />
<span data-i18n="Only Format Display">Alter Chat Display</span>
</label>

View File

@ -189,8 +189,8 @@ async function validateGroup(group) {
group.members = group.members.filter(member => {
const character = characters.find(x => x.avatar === member || x.name === member);
if (!character) {
const msg = `Warning: Listed member ${member} does not exist as a character. It will be removed from the group.`;
toastr.warning(msg, 'Group Validation');
const msg = t`Warning: Listed member ${member} does not exist as a character. It will be removed from the group.`;
toastr.warning(msg, t`Group Validation`);
console.warn(msg);
dirty = true;
}
@ -522,7 +522,7 @@ async function saveGroupChat(groupId, shouldSaveGroup) {
});
if (!response.ok) {
toastr.error('Check the server connection and reload the page to prevent data loss.', 'Group Chat could not be saved');
toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Group Chat could not be saved`);
console.error('Group chat could not be saved', response);
return;
}
@ -837,7 +837,7 @@ async function generateGroupWrapper(by_auto_mode, type = null, params = {}) {
activatedMembers = activateSwipe(group.members);
if (activatedMembers.length === 0) {
toastr.warning('Deleted group member swiped. To get a reply, add them back to the group.');
toastr.warning(t`Deleted group member swiped. To get a reply, add them back to the group.`);
throw new Error('Deleted group member swiped');
}
}
@ -1368,15 +1368,15 @@ function isGroupMemberDisabled(avatarId) {
async function onDeleteGroupClick() {
if (!openGroupId) {
toastr.warning('Currently no group selected.');
toastr.warning(t`Currently no group selected.`);
return;
}
if (is_group_generating) {
toastr.warning('Not so fast! Wait for the characters to stop typing before deleting the group.');
toastr.warning(t`Not so fast! Wait for the characters to stop typing before deleting the group.`);
return;
}
const confirm = await Popup.show.confirm('Delete the group?', '<p>This will also delete all your chats with that group. If you want to delete a single conversation, select a "View past chats" option in the lower left menu.</p>');
const confirm = await Popup.show.confirm(t`Delete the group?`, '<p>' + t`This will also delete all your chats with that group. If you want to delete a single conversation, select a "View past chats" option in the lower left menu.` + '</p>');
if (confirm) {
deleteGroup(openGroupId);
}
@ -1630,7 +1630,7 @@ function updateFavButtonState(state) {
export async function openGroupById(groupId) {
if (isChatSaving) {
toastr.info('Please wait until the chat is saved before switching characters.', 'Your chat is still saving...');
toastr.info(t`Please wait until the chat is saved before switching characters.`, t`Your chat is still saving...`);
return;
}
@ -1659,7 +1659,7 @@ export async function openGroupById(groupId) {
function openCharacterDefinition(characterSelect) {
if (is_group_generating) {
toastr.warning('Can\'t peek a character while group reply is being generated');
toastr.warning(t`Can't peek a character while group reply is being generated`);
console.warn('Can\'t peek a character def while group reply is being generated');
return;
}
@ -1908,7 +1908,7 @@ export async function saveGroupBookmarkChat(groupId, name, metadata, mesId) {
});
if (!response.ok) {
toastr.error('Check the server connection and reload the page to prevent data loss.', 'Group chat could not be saved');
toastr.error(t`Check the server connection and reload the page to prevent data loss.`, t`Group chat could not be saved`);
console.error('Group chat could not be saved', response);
}
}

View File

@ -388,7 +388,7 @@ async function validateReverseProxy() {
new URL(oai_settings.reverse_proxy);
}
catch (err) {
toastr.error('Entered reverse proxy address is not a valid URL');
toastr.error(t`Entered reverse proxy address is not a valid URL`);
setOnlineStatus('no_connection');
resultCheckStatus();
throw err;
@ -399,7 +399,7 @@ async function validateReverseProxy() {
const confirmation = skipConfirm || await Popup.show.confirm(t`Connecting To Proxy`, await renderTemplateAsync('proxyConnectionWarning', { proxyURL: DOMPurify.sanitize(oai_settings.reverse_proxy) }));
if (!confirmation) {
toastr.error('Update or remove your reverse proxy settings.');
toastr.error(t`Update or remove your reverse proxy settings.`);
setOnlineStatus('no_connection');
resultCheckStatus();
throw new Error('Proxy connection denied.');
@ -1231,15 +1231,15 @@ export async function prepareOpenAIMessages({
await populateChatCompletion(prompts, chatCompletion, { bias, quietPrompt, quietImage, type, cyclePrompt, messages, messageExamples });
} catch (error) {
if (error instanceof TokenBudgetExceededError) {
toastr.error('An error occurred while counting tokens: Token budget exceeded.');
toastr.error(t`An error occurred while counting tokens: Token budget exceeded.`);
chatCompletion.log('Token budget exceeded.');
promptManager.error = 'Not enough free tokens for mandatory prompts. Raise your token Limit or disable custom prompts.';
promptManager.error = t`Not enough free tokens for mandatory prompts. Raise your token Limit or disable custom prompts.`;
} else if (error instanceof InvalidCharacterNameError) {
toastr.warning('An error occurred while counting tokens: Invalid character name');
toastr.warning(t`An error occurred while counting tokens: Invalid character name`);
chatCompletion.log('Invalid character name');
promptManager.error = 'The name of at least one character contained whitespaces or special characters. Please check your user and character name.';
promptManager.error = t`The name of at least one character contained whitespaces or special characters. Please check your user and character name.`;
} else {
toastr.error('An unknown error occurred while counting tokens. Further information may be available in console.');
toastr.error(t`An unknown error occurred while counting tokens. Further information may be available in console.`);
chatCompletion.log('----- Unexpected error while preparing prompts -----');
chatCompletion.log(error);
chatCompletion.log(error.stack);
@ -1293,11 +1293,8 @@ function tryParseStreamingError(response, decoded) {
}
}
function checkQuotaError(data) {
const errorText = `<h3>Encountered an error while processing your request.<br>
Check you have credits available on your
<a href="https://platform.openai.com/account/usage" target="_blank">OpenAI account</a>.<br>
If you have sufficient credits, please try again later.</h3>`;
async function checkQuotaError(data) {
const errorText = await renderTemplateAsync('quotaError');
if (!data) {
return;
@ -1933,11 +1930,11 @@ async function sendOpenAIRequest(type, messages, signal) {
else {
const data = await response.json();
checkQuotaError(data);
await checkQuotaError(data);
checkModerationError(data);
if (data.error) {
toastr.error(data.error.message || response.statusText, 'API returned an error');
toastr.error(data.error.message || response.statusText, t`API returned an error`);
throw new Error(data);
}
@ -2184,7 +2181,7 @@ function parseOpenAITextLogprobs(logprobs) {
function handleWindowError(err) {
const text = parseWindowError(err);
toastr.error(text, 'Window.ai returned an error');
toastr.error(text, t`Window.ai returned an error`);
throw err;
}
@ -3257,7 +3254,7 @@ async function getStatusOpen() {
}
function showWindowExtensionError() {
toastr.error('Get it here: <a href="https://windowai.io/" target="_blank">windowai.io</a>', 'Extension is not installed', {
toastr.error(t`Get it here:` + ' <a href="https://windowai.io/" target="_blank">windowai.io</a>', t`Extension is not installed`, {
escapeHtml: false,
timeOut: 0,
extendedTimeOut: 0,
@ -3376,7 +3373,7 @@ async function saveOpenAIPreset(name, settings, triggerUi = true) {
if (triggerUi) $('#settings_preset_openai').append(option).trigger('change');
}
} else {
toastr.error('Failed to save preset');
toastr.error(t`Failed to save preset`);
throw new Error('Failed to save preset');
}
}
@ -3455,7 +3452,7 @@ async function createNewLogitBiasPreset() {
}
if (name in oai_settings.bias_presets) {
toastr.error('Preset name should be unique.');
toastr.error(t`Preset name should be unique.`);
return;
}
@ -3499,7 +3496,7 @@ async function onPresetImportFileChange(e) {
try {
presetBody = JSON.parse(importedFile);
} catch (err) {
toastr.error('Invalid file');
toastr.error(t`Invalid file`);
return;
}
@ -3540,7 +3537,7 @@ async function onPresetImportFileChange(e) {
});
if (!savePresetSettings.ok) {
toastr.error('Failed to save preset');
toastr.error(t`Failed to save preset`);
return;
}
@ -3565,7 +3562,7 @@ async function onPresetImportFileChange(e) {
async function onExportPresetClick() {
if (!oai_settings.preset_settings_openai) {
toastr.error('No preset selected');
toastr.error(t`No preset selected`);
return;
}
@ -3606,12 +3603,12 @@ async function onLogitBiasPresetImportFileChange(e) {
e.target.value = '';
if (name in oai_settings.bias_presets) {
toastr.error('Preset name should be unique.');
toastr.error(t`Preset name should be unique.`);
return;
}
if (!Array.isArray(importedFile)) {
toastr.error('Invalid logit bias preset file.');
toastr.error(t`Invalid logit bias preset file.`);
return;
}
@ -3670,16 +3667,16 @@ async function onDeletePresetClick() {
});
if (!response.ok) {
toastr.warning('Preset was not deleted from server');
toastr.warning(t`Preset was not deleted from server`);
} else {
toastr.success('Preset deleted');
toastr.success(t`Preset deleted`);
}
saveSettingsDebounced();
}
async function onLogitBiasPresetDeleteClick() {
const value = await callPopup('Delete the preset?', 'confirm');
const value = await callPopup(t`Delete the preset?`, 'confirm');
if (!value) {
return;
@ -4816,7 +4813,7 @@ function runProxyCallback(_, value) {
const result = fuse.search(value);
if (result.length === 0) {
toastr.warning(`Proxy preset "${value}" not found`);
toastr.warning(t`Proxy preset '${value}' not found`);
return '';
}
@ -4990,7 +4987,7 @@ export function initOpenAI() {
$('#update_oai_preset').on('click', async function () {
const name = oai_settings.preset_settings_openai;
await saveOpenAIPreset(name, oai_settings);
toastr.success('Preset updated');
toastr.success(t`Preset updated`);
});
$('#impersonation_prompt_restore').on('click', function () {

View File

@ -1,3 +1,3 @@
<div>
<b>Note:</b> this chat is temporary and will be deleted as soon as you leave it.
<b data-i18n="Note:">Note:</b> <span data-i18n="this chat is temporary and will be deleted as soon as you leave it.">this chat is temporary and will be deleted as soon as you leave it.</span>
</div>

View File

@ -0,0 +1,5 @@
<b><span data-i18n="THIS IS PERMANENT!">THIS IS PERMANENT!</span><br><br>
<label for="del_char_checkbox" class="checkbox_label justifyCenter">
<input type="checkbox" id="del_char_checkbox" />
<small data-i18n="Also delete the chat files">Also delete the chat files</small>
</label></b>

View File

@ -1,5 +1,5 @@
<div>
<h3>Are you sure you want to duplicate this character?</h3>
<span>If you just want to start a new chat with the same character, use "Start new chat" option in the bottom-left options menu.</span>
<h3 data-i18n="Are you sure you want to duplicate this character?">Are you sure you want to duplicate this character?</h3>
<span data-i18n="If you just want to start a new chat with the same character...">If you just want to start a new chat with the same character, use "Start new chat" option in the bottom-left options menu.</span>
<br>
</div>

View File

@ -14,18 +14,18 @@
<li><kbd data-i18n="help_hotkeys_19">Ctrl+Shift+Down</kbd> = <span data-i18n="help_hotkeys_20">Scroll chat to bottom</span></li>
</ul>
<div>
<strong>Markdown Hotkeys</strong>
<strong data-i18n="help_hotkeys_20">Markdown Hotkeys</strong>
</div>
<div>
<small>
<span>Works in the chatbar and textareas marked with this icon:</span>
<span data-i18n="help_hotkeys_21">Works in the chatbar and textareas marked with this icon:</span>
<code><i class="fa-brands fa-markdown"></i></code>
</small>
</div>
<ul>
<li><kbd>Ctrl+B</kbd> = <span>**bold**</span></li>
<li><kbd>Ctrl+I</kbd> = <span>*italic*</span></li>
<li><kbd>Ctrl+U</kbd> = <span>__underline__</span></li>
<li><kbd>Ctrl+K</kbd> = <span>`inline code`</span></li>
<li><kbd>Ctrl+Shift+~</kbd> = <span>~~strikethrough~~</span></li>
<li><kbd>Ctrl+B</kbd> = <span data-i18n="help_hotkeys_22">**bold**</span></li>
<li><kbd>Ctrl+I</kbd> = <span data-i18n="help_hotkeys_23">*italic*</span></li>
<li><kbd>Ctrl+U</kbd> = <span data-i18n="help_hotkeys_24">__underline__</span></li>
<li><kbd>Ctrl+K</kbd> = <span data-i18n="help_hotkeys_25">`inline code`</span></li>
<li><kbd>Ctrl+Shift+~</kbd> = <span data-i18n="help_hotkeys_26">~~strikethrough~~</span></li>
</ul>

View File

@ -0,0 +1,4 @@
<h3><span data-i18n="Encountered an error while processing your request.">Encountered an error while processing your request.</span><br>
<span data-i18n="Check you have credits available on your">Check you have credits available on your</span>
<a href="https://platform.openai.com/account/usage" target="_blank" data-i18n="OpenAI account quora_error">OpenAI account</a><span data-i18n="dot quota_error">.</span><br>
<span data-i18n="If you have sufficient credits, please try again later.">If you have sufficient credits, please try again later.</span></h3>