mirror of
https://github.com/SillyTavern/SillyTavern.git
synced 2025-02-22 23:18:27 +01:00
Merge branch 'staging' into frFr
This commit is contained in:
commit
5734722c5d
@ -2278,7 +2278,7 @@
|
||||
<h4 data-i18n="Model Providers">Model Providers</h4>
|
||||
<select id="openrouter_providers_text" class="openrouter_providers" multiple>
|
||||
</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" />
|
||||
<span data-i18n="Allow fallback providers">Allow fallback providers</span>
|
||||
</label>
|
||||
@ -2902,7 +2902,7 @@
|
||||
<div>
|
||||
<h4 data-i18n="Window AI Model">Window AI Model</h4>
|
||||
<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-16k">openai/gpt-3.5-turbo-16k</option>
|
||||
<option value="openai/gpt-4">openai/gpt-4</option>
|
||||
@ -2977,14 +2977,14 @@
|
||||
<h4 data-i18n="Model Providers">Model Providers</h4>
|
||||
<select id="openrouter_providers_chat" class="openrouter_providers" multiple>
|
||||
</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" />
|
||||
<span data-i18n="Allow fallback providers">Allow fallback providers</span>
|
||||
</label>
|
||||
</div>
|
||||
<small class="marginTopBot5">
|
||||
<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>
|
||||
</form>
|
||||
<form id="scale_form" data-source="scale" action="javascript:void(null);" method="post" enctype="multipart/form-data">
|
||||
@ -3319,7 +3319,7 @@
|
||||
</div>
|
||||
<h4 data-i18n="Enter a Model ID">Enter a Model ID</h4>
|
||||
<div class="flex-container">
|
||||
<input list="model_custom_select_fill" id="custom_model_id" class="text_pole wide100p" value="" autocomplete="off" data-i18n="[placeholder]Example: gpt-3.5-turbo" placeholder="Example: gpt-3.5-turbo">
|
||||
<input list="model_custom_select_fill" id="custom_model_id" class="text_pole wide100p" value="" autocomplete="off" data-i18n="[placeholder]Example: gpt-4o" placeholder="Example: gpt-4o">
|
||||
<datalist id="model_custom_select_fill" class="text_pole model_custom_select"></datalist>
|
||||
</div>
|
||||
<h4 data-i18n="Available Models">Available Models</h4>
|
||||
@ -4601,7 +4601,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<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>
|
||||
<div class="fa-solid fa-circle-chevron-down inline-drawer-icon down"></div>
|
||||
</div>
|
||||
@ -5734,7 +5734,7 @@
|
||||
<span class="drag-handle">☰</span>
|
||||
<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="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="WIEntryTitleAndStatus flex-container flex1 alignitemscenter">
|
||||
<div class="flex-container flex1">
|
||||
@ -5967,7 +5967,7 @@
|
||||
</small>
|
||||
</div>
|
||||
<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]Non-sticky" placeholder="Non-sticky" min="0" max="999999">
|
||||
</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.">
|
||||
@ -5980,7 +5980,7 @@
|
||||
</small>
|
||||
</div>
|
||||
<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 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>
|
||||
</div>
|
||||
<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>
|
||||
|
@ -879,7 +879,7 @@
|
||||
"popup-button-no": "لا",
|
||||
"popup-button-cancel": "يلغي",
|
||||
"popup-button-import": "يستورد",
|
||||
"Advanced Defininitions": "تعريفات متقدمة",
|
||||
"Advanced Definitions": "تعريفات متقدمة",
|
||||
"Prompt Overrides": "التجاوزات السريعة",
|
||||
"(For Chat Completion and Instruct Mode)": "(لاستكمال الدردشة ووضع التعليمات)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "أدخل {{original}} في أي مربع لتضمين التعليمات الافتراضية المعنية من إعدادات النظام.",
|
||||
|
@ -879,7 +879,7 @@
|
||||
"popup-button-no": "NEIN",
|
||||
"popup-button-cancel": "Stornieren",
|
||||
"popup-button-import": "Importieren",
|
||||
"Advanced Defininitions": "Erweiterte Definitionen",
|
||||
"Advanced Definitions": "Erweiterte Definitionen",
|
||||
"Prompt Overrides": "Eingabeaufforderungsüberschreibungen",
|
||||
"(For Chat Completion and Instruct Mode)": "(Für Chat-Abschluss und Anweisungsmodus)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Füge {{original}} in eines der Felder ein, um den jeweiligen Standardprompt aus den Systemeinstellungen einzuschließen.",
|
||||
|
@ -879,7 +879,7 @@
|
||||
"popup-button-no": "No",
|
||||
"popup-button-cancel": "Cancelar",
|
||||
"popup-button-import": "Importar",
|
||||
"Advanced Defininitions": "Definiciones avanzadas",
|
||||
"Advanced Definitions": "Definiciones avanzadas",
|
||||
"Prompt Overrides": "Anulaciones rápidas",
|
||||
"(For Chat Completion and Instruct Mode)": "(Para completar el chat y el modo de instrucción)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Inserte {{original}} en cualquiera de las casillas para incluir las indicaciones predeterminadas respectivas de la configuración del sistema.",
|
||||
@ -1439,5 +1439,112 @@
|
||||
"Still have questions?": "¿Todavía tienes preguntas?",
|
||||
"Join the SillyTavern Discord": "Únete al Discord de SillyTavern",
|
||||
"Post a GitHub issue": "Publicar un problema en GitHub",
|
||||
"Contact the developers": "Contactar a los desarrolladores"
|
||||
"Contact the developers": "Contactar a los desarrolladores",
|
||||
"Prome (Visual Novel Extension)": "Prome (Extensión de Modo Waifu/Novela Visual)",
|
||||
"Brought to you by": "Presentado por",
|
||||
"and Prometheus.": "y Prometheus.",
|
||||
"Enable Prome": "Iniciar Prome",
|
||||
"Toggles Prome, VN Mode and other Prome features.": "Activa Prome, el modo VN y otras funciones de Prome.",
|
||||
"Features marked with a": "Las funciones marcadas con un",
|
||||
"require Prome to be enabled.": "requieren que Prome esté iniciado.",
|
||||
"Sheld Configuration": "Configuración de interfaz (Sheld)",
|
||||
"Hide Sheld (Message Box)": "Ocultar Sheld (cuadro de mensajes)",
|
||||
"Hide the message box (sheld) in the ST UI.": "Ocultar el cuadro de mensajes (sheld) en la interfaz de usuario de SillyTavern.",
|
||||
"Enable Traditional VN Mode": "Modo VN tradicional*",
|
||||
"Only Show Last Message in Chat (Requires Prome to be enabled).": "Mostrar solo el último mensaje en el chat (Requiere que Prome esté iniciado).",
|
||||
"Letterbox Configuration*": "Configuración de la franja negra*",
|
||||
"Letterbox Mode": "Modo de franja negra",
|
||||
"Select the letterbox mode for the Prome VN UI.": "Seleccione el modo de franja negra para la interfaz de usuario VN de Prome.",
|
||||
"Horizontal Letterbox": "Franja negra horizontal",
|
||||
"Vertical Letterbox": "Franja negra vertical",
|
||||
"Letterbox Color": "Color de la franja negra",
|
||||
"Select the color of the letterbox.": "Seleccione el color de la franja negra.",
|
||||
"Letterbox Size": "Tamaño de la franja negra",
|
||||
"Set the size of the letterbox.": "Establezca el tamaño de la franja negra.",
|
||||
"Sprite Configuration": "Configuración de sprites",
|
||||
"Emulate Character Card as Sprite": "[BETA] Emular tarjeta de personaje como sprite",
|
||||
"Emulates the character card of a character to be a sprite. (Requires Prome to be enabled).": "Emula la tarjeta de personaje de un personaje para que sea un sprite. (Requiere que Prome esté iniciado).",
|
||||
"Enable Sprite Shake": "[BETA] Sprite Shake",
|
||||
"Shakes the character sprite when the character is speaking (Only works if Streaming is enabled in Preset Settings).": "Agita el sprite del personaje cuando el personaje está hablando (solo funciona si la transmisión está habilitada en la configuración preestablecida).",
|
||||
"Enable Focus Mode": "Modo de enfoque",
|
||||
"Focuses the current speaking character in chat. (Requires Prome to be enabled).": "Enfoca al personaje que está hablando en el chat. (Requiere que Prome esté iniciado).",
|
||||
"Darken Unfocused Character Sprites": "Oscurecer sprites de personajes",
|
||||
"Darkens non-speaking (unfocused) characters. (Requires Prome to be enabled).": "Oscurece a los personajes que no hablan (no enfocados). (Requiere que Prome esté iniciado).",
|
||||
"Auto-Hide Sprites": "Ocultar sprites automáticamente",
|
||||
"Auto-hides characters from the screen that haven't been in the conversation for a while up to X characters. (Requires Prome to be enabled).": "Oculta automáticamente a los personajes de la pantalla que no han estado en la conversación durante un tiempo hasta X personajes. (Requiere que Prome esté iniciado).",
|
||||
"Max Visible Sprites": "Máximo de personajes visibles",
|
||||
"Set the maximum number of visible sprites that appears in the VN screen.": "Establezca el número máximo de sprites visibles que aparecen en la pantalla VN.",
|
||||
"Sprite Shadow Configuration": "Configuración de sombra de sprites",
|
||||
"Enable Sprite Shadow": "Sombra de sprite",
|
||||
"Adds a shadow to the character sprite.": "Agrega una sombra al sprite del personaje.",
|
||||
"Shadow X Offset": "Desplazamiento X de la sombra",
|
||||
"Set the X offset of the character shadow.": "Establezca el desplazamiento X de la sombra del personaje.",
|
||||
"Shadow Y Offset": "Desplazamiento Y de la sombra",
|
||||
"Set the Y offset of the character shadow.": "Establezca el desplazamiento Y de la sombra del personaje.",
|
||||
"Shadow Blur": "Desenfoque de sombra",
|
||||
"Set the blur of the character shadow.": "Establezca el desenfoque de la sombra del personaje.",
|
||||
"Focus Mode Settings": "Configuración del modo de enfoque",
|
||||
"Focus Mode Animation": "Animación de modo de enfoque",
|
||||
"Select the animation for focus mode.": "Seleccione la animación para el modo de enfoque.",
|
||||
"Focus Mode Animation Speed": "Velocidad de animación del modo de enfoque",
|
||||
"Set the speed of the focus animation.": "Establezca la velocidad de la animación de enfoque.",
|
||||
"User Sprite Configuration": "[BETA] Configuración de sprites de usuario",
|
||||
"Enable User Sprite": "Sprites de usuario",
|
||||
"Enables the ability to use a user sprite for your persona.": "Habilita la capacidad de usar un sprite de usuario para tu persona.",
|
||||
"Sprite set": "Conjunto de sprites",
|
||||
"Type the name of the sprite set to use for your persona. (Place your sprites in the 'characters' folder in SillyTavern).": "Escriba el nombre del conjunto de sprites que desea utilizar para su persona. (Coloque sus sprites en la carpeta 'characters' en SillyTavern).",
|
||||
"Note: Create a sprite folder in the ": "Nota: Cree una carpeta de sprites en el ",
|
||||
" folder of your user directory (typically 'data/default-user'). Place your expressions there.": " carpeta de su directorio de usuario (normalmente 'data/default-user'). Coloque sus expresiones allí.",
|
||||
"Tint Configuration": "Configuración de tono",
|
||||
"Enable Chat Tint": "Tinte de chat",
|
||||
"Tints the chat background and/or character sprites.": "Tinta el fondo del chat y/o los sprites de personajes.",
|
||||
"Share World Tint With Characters": "Compartir tinte mundial con personajes*",
|
||||
"Applies the world tint to character sprites (Requires Prome to be enabled. This will override your character tint settings).": "Aplica el tinte mundial a los sprites de personajes (Requiere que Prome esté iniciado. Esto anulará la configuración de tinte de su personaje).",
|
||||
"Tint Presets": "Preajustes de tinte",
|
||||
"Select the tint preset to use for the Prome VN UI.": "Seleccione el preajuste de tinte que desea utilizar para la interfaz de usuario VN de Prome.",
|
||||
"World Tint Settings": "Configuración de tinte mundial",
|
||||
"Tints the world background.": "Tinta el fondo mundial.",
|
||||
"Enable World Tint": "Tinte mundial",
|
||||
"Set the strength of the world blur.": "Establezca la fuerza del desenfoque mundial.",
|
||||
"Brightness": "Brillo",
|
||||
"Set the brightness of the world.": "Establezca el brillo del mundo.",
|
||||
"Contrast": "Contraste",
|
||||
"Set the contrast of the world.": "Establezca el contraste del mundial.",
|
||||
"Grayscale": "Escala de grises",
|
||||
"Makes the world black and white.": "Hace que el mundo sea en blanco y negro.",
|
||||
"Hue": "Matiz",
|
||||
"Set the hue of the world tint.": "Establezca el matiz del tinte mundial.",
|
||||
"Invert": "Invertir",
|
||||
"Inverts the world colors.": "Invierte los colores del mundo.",
|
||||
"Saturate": "Saturar",
|
||||
"Saturates the world colors.": "Satura los colores del mundo.",
|
||||
"Makes the world warmer in color.": "Hace que el mundo sea más cálido en color.",
|
||||
"Character Tint Settings": "Configuración de tinte de sprites*",
|
||||
"Enable Character Tint (Requires Prome to be enabled)": "Tinte de sprites (Requiere que Prome esté iniciado)",
|
||||
"Set the strength of the character blur.": "Establezca la fuerza del desenfoque de personajes.",
|
||||
"Set the brightness of the character.": "Establezca el brillo de personaje.",
|
||||
"Set the contrast of the character.": "Establezca el contraste de personajes.",
|
||||
"Makes the character black and white.": "Hace que el personaje sea en blanco y negro.",
|
||||
"Set the hue of the character.": "Establezca el matiz del tinte de personajes.",
|
||||
"Inverts the character colors.": "Invierte los colores del personaje.",
|
||||
"Saturates the character colors.": "Satura los colores del personaje.",
|
||||
"Makes the character warmer in color.": "Hace que el personaje sea más cálido en color.",
|
||||
"Keybinds": "Atajos de teclado",
|
||||
"Commands": "Comandos",
|
||||
"Prome Keybinds": "Combinaciones de teclas de Prome",
|
||||
"Hide/Show SillyTavern's Sheld (Message Box)": "Ocultar/Mostrar el estante de SillyTavern (cuadro de mensaje)",
|
||||
"Prome Commands": "Comandos de Prome",
|
||||
"Show/Hide the letterbox (black bars) in the VN UI": "Mostrar/Ocultar la franja negra (barras negras) en la interfaz VN",
|
||||
"Toggles focus mode on character sprites": "Alterna el modo de enfoque en los sprites de personajes",
|
||||
"Sets the focus mode animation": "Establece la animación del modo de enfoque",
|
||||
"Toggles the defocus tint on non-speaking character sprites": "Alterna el tinte de desenfoque en los sprites de personajes que no hablan",
|
||||
"Toggles the shake animation when a character speaks on character sprites": "Alterna la animación de sacudida cuando un personaje habla en los sprites de personajes",
|
||||
"Toggles sprite shadows on character sprites": "Alterna las sombras de los sprites de personajes",
|
||||
"Toggles world/character tint on the VN UI": "Alterna el tinte mundial/de personajes en la interfaz VN",
|
||||
"Toggles world tint on the VN UI": "Alterna el tinte mundial en la interfaz VN",
|
||||
"Toggles character tint on the VN UI": "Alterna el tinte de personajes en la interfaz VN",
|
||||
"Toggles sharing world tint with character sprites (This will override Character Tint)": "Alterna el tinte mundial compartido con los sprites de personajes (esto anulará el tinte de personajes)",
|
||||
"Sets the expression of the user sprite": "Establece la expresión del sprite de usuario",
|
||||
"Sets the user sprite set to use for the user sprite": "Establece el conjunto de sprites de usuario para usar en el sprite de usuario",
|
||||
"Toggles the user sprite on the VN UI": "Alterna el sprite de usuario en la interfaz VN"
|
||||
}
|
||||
|
@ -823,11 +823,13 @@
|
||||
"popup-button-no": "Non",
|
||||
"popup-button-cancel": "Annuler",
|
||||
"popup-button-import": "Importer",
|
||||
"Prompt Overrides": "Remplacements de prompt",
|
||||
"(For Chat Completion and Instruct Mode)": "(Pour la complétion de chat et le mode instruction)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Insérez {{original}} dans l'un ou l'autre des champs pour inclure le prompt par défaut correspondante dans les paramètres système.",
|
||||
"Main Prompt": "Prompt principal",
|
||||
"Any contents here will replace the default Main Prompt used for this character. (v2 spec: system_prompt)": "Tout contenu ici remplacera le prompt principal par défaut utilisée pour ce personnage. (spéc v2 : system_prompt)",
|
||||
"Advanced Definitions": "Définitions avancées",
|
||||
"Prompt Overrides": "Remplacements d'invite",
|
||||
"(For Chat Completion and Instruct Mode)": "(Pour l'achèvement du chat et le mode instruction)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Insérez {{original}} dans l'un ou l'autre des champs pour inclure l'instruction par défaut respective des paramètres système.",
|
||||
"Main Prompt": "Instruction principale",
|
||||
"Any contents here will replace the default Main Prompt used for this character. (v2 spec: system_prompt)": "Tout contenu ici remplacera l'instruction principale par défaut utilisée pour ce personnage. (spécification v2 : système_prompt)",
|
||||
"Any contents here will replace the default Jailbreak Prompt used for this character. (v2 spec: post_history_instructions)": "Tout contenu ici remplacera l'instruction de jailbreak par défaut utilisée pour ce personnage. (spécification v2 : post_history_instructions)",
|
||||
"Creator's Metadata (Not sent with the AI prompt)": "Métadonnées du créateur (Non envoyées avec l'instruction de l'IA)",
|
||||
"Creator's Metadata": "Métadonnées du créateur",
|
||||
"(Not sent with the AI Prompt)": "(Non envoyé avec le prompt IA)",
|
||||
@ -2041,7 +2043,6 @@
|
||||
"Strategy": "Stratégie",
|
||||
"Position": "Position",
|
||||
"Trigger %": "Déclencheur %",
|
||||
"Advanced Definitions": "- Définitions\n Avancé",
|
||||
"Only chunk on custom boundary": "Only chunk on custom boundary",
|
||||
"Generate Caption": "Générer une légende",
|
||||
"Use System Prompt": "Utiliser le prompt système:",
|
||||
|
@ -879,7 +879,7 @@
|
||||
"popup-button-no": "Nei",
|
||||
"popup-button-cancel": "Hætta við",
|
||||
"popup-button-import": "Flytja inn",
|
||||
"Advanced Defininitions": "Ítarleg skilgreiningar",
|
||||
"Advanced Definitions": "Ítarleg skilgreiningar",
|
||||
"Prompt Overrides": "Hnekkja hvetjandi",
|
||||
"(For Chat Completion and Instruct Mode)": "(Til að ljúka spjalli og leiðbeiningarham)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Settu inn {{original}} í hvora kassa til að innifela viðkomandi sjálfgefna framkallan frá kerfisstillingum.",
|
||||
|
@ -879,7 +879,7 @@
|
||||
"popup-button-no": "NO",
|
||||
"popup-button-cancel": "Annulla",
|
||||
"popup-button-import": "Importare",
|
||||
"Advanced Defininitions": "Definizioni avanzate",
|
||||
"Advanced Definitions": "Definizioni avanzate",
|
||||
"Prompt Overrides": "Sostituzioni richieste",
|
||||
"(For Chat Completion and Instruct Mode)": "(Per il completamento della chat e la modalità istruzione)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Inserisci {{originale}} in uno dei due riquadri per includere il prompt predefinito corrispondente dalle impostazioni di sistema.",
|
||||
|
@ -879,7 +879,7 @@
|
||||
"popup-button-no": "いいえ",
|
||||
"popup-button-cancel": "キャンセル",
|
||||
"popup-button-import": "インポート",
|
||||
"Advanced Defininitions": "高度な定義",
|
||||
"Advanced Definitions": "高度な定義",
|
||||
"Prompt Overrides": "プロンプトのオーバーライド",
|
||||
"(For Chat Completion and Instruct Mode)": "(チャット補完と指示モード用)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "システム設定からの対応するデフォルトのプロンプトを含めるには、どちらかのボックスに{{original}}を挿入します。",
|
||||
|
@ -895,7 +895,7 @@
|
||||
"popup-button-no": "아니요",
|
||||
"popup-button-cancel": "취소",
|
||||
"popup-button-import": "불러오기",
|
||||
"Advanced Defininitions": "고급 정의",
|
||||
"Advanced Definitions": "고급 정의",
|
||||
"Prompt Overrides": "프롬프트 무시",
|
||||
"(For Chat Completion and Instruct Mode)": "(채팅 완료 및 지시 모드의 경우)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "{{original}}를 해당 상자에 넣어 시스템 설정의 기본 프롬프트를 포함합니다.",
|
||||
|
@ -879,7 +879,7 @@
|
||||
"popup-button-no": "Nee",
|
||||
"popup-button-cancel": "Annuleren",
|
||||
"popup-button-import": "Importeren",
|
||||
"Advanced Defininitions": "Geavanceerde definities",
|
||||
"Advanced Definitions": "Geavanceerde definities",
|
||||
"Prompt Overrides": "Prompt-overschrijvingen",
|
||||
"(For Chat Completion and Instruct Mode)": "(Voor voltooiing van chat en instructiemodus)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Voeg {{original}} in in elk vak in om de respectievelijke standaardprompt vanuit systeeminstellingen op te nemen.",
|
||||
|
@ -879,7 +879,7 @@
|
||||
"popup-button-no": "Não",
|
||||
"popup-button-cancel": "Cancelar",
|
||||
"popup-button-import": "Importar",
|
||||
"Advanced Defininitions": "Definições Avançadas",
|
||||
"Advanced Definitions": "Definições Avançadas",
|
||||
"Prompt Overrides": "Substituições de prompt",
|
||||
"(For Chat Completion and Instruct Mode)": "(Para conclusão de bate-papo e modo de instrução)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Insira {{original}} em qualquer caixa para incluir o prompt padrão respectivo das configurações do sistema.",
|
||||
|
@ -265,7 +265,7 @@
|
||||
"Current Members": "Текущие участники",
|
||||
"Delete": "Удалить",
|
||||
"Cancel": "Отменить",
|
||||
"Advanced Defininitions": "Расширенное описание",
|
||||
"Advanced Definitions": "Расширенное описание",
|
||||
"Personality summary": "Резюме по личности",
|
||||
"Scenario": "Сценарий",
|
||||
"Talkativeness": "Разговорчивость",
|
||||
@ -294,7 +294,7 @@
|
||||
"Avoid sending sensitive information to the Horde.": "Избегайте отправки личной информации Horde",
|
||||
"Review the Privacy statement": "Ознакомиться с заявлением о конфиденциальности",
|
||||
"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 не загружена--",
|
||||
"Example: http://127.0.0.1:5000/api ": "Пример: http://127.0.0.1:5000/api",
|
||||
"No connection...": "Нет соединения...",
|
||||
@ -331,7 +331,6 @@
|
||||
"UID ↘": "UID ↘",
|
||||
"Trigger% ↗": "Триггер% ↗",
|
||||
"Trigger% ↘": "Триггер% ↘",
|
||||
"Order:": "Порядок:",
|
||||
"Depth:": "Глубина:",
|
||||
"Character Lore First": "Сначала лор персонажа",
|
||||
"Global Lore First": "Сначала глобальный лор",
|
||||
@ -347,7 +346,7 @@
|
||||
"After Char Defs": "↓Перс.",
|
||||
"Before AN": "↑АЗ",
|
||||
"After AN": "↓АЗ",
|
||||
"Order": "Порядок:",
|
||||
"Order": "Очерёдность:",
|
||||
"Update a theme file": "Обновить файл темы",
|
||||
"Save as a new theme": "Сохранить как новую тему",
|
||||
"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": "Что это ключевое слово должно означать для ИИ, отправляется дословно",
|
||||
"Filter to Character(s)": "Фильтр по персонажу(ам)",
|
||||
"Character Exclusion": "Исключить персонажей",
|
||||
"Inclusion Group": "Включить персонажей",
|
||||
"Inclusion Group": "Группа записей",
|
||||
"Only one entry with the same label will be activated": "Будет активна только одна запись с одинаковой меткой",
|
||||
"-- Characters not found --": "-- Персонажей не найдено --",
|
||||
"(This will be the first message from the character that starts every chat)": "(Это будет первое сообщение от персонажа, когда вы начинаете новый чат)",
|
||||
@ -541,7 +540,7 @@
|
||||
"NOT ANY": "НЕ ЛЮБОЙ",
|
||||
"Optional Filter": "Дополнительный фильтр",
|
||||
"New Entry": "Новая запись",
|
||||
"Fill empty Memo/Titles with Keywords": "Заполните пустые Заметки/Названия ключевыми словами",
|
||||
"Fill empty Memo/Titles with Keywords": "Заполнить пустые названия ключевыми словами",
|
||||
"AI Response Formatting": "Формат ответа ИИ",
|
||||
"Change Background Image": "Изменить фон",
|
||||
"Extensions": "Расширения",
|
||||
@ -628,7 +627,7 @@
|
||||
"UI Theme": "Тема UI",
|
||||
"This message is invisible for the AI": "Это сообщение невидимо для ИИ",
|
||||
"Sampler Priority": "Приоритет сэмплеров",
|
||||
"Ooba only. Determines the order of samplers.": "Только Ooba. Определяет порядок сэмплеров.",
|
||||
"Ooba only. Determines the order of samplers.": "Только oobabooga. Определяет порядок сэмплеров.",
|
||||
"Load default order": "Загрузить стандартный порядок",
|
||||
"Max Tokens Second": "Макс. кол-во токенов в секунду",
|
||||
"CFG": "CFG",
|
||||
@ -1132,7 +1131,7 @@
|
||||
"Custom API Key": "Ключ от кастомного API",
|
||||
"(Optional)": "(необязательно)",
|
||||
"Enter a Model ID": "Введите идентификатор модели",
|
||||
"Example: gpt-3.5-turbo": "Пример: gpt-3.5-turbo",
|
||||
"Example: gpt-4o": "Пример: gpt-4o",
|
||||
"Available Models": "Доступные модели",
|
||||
"Prompt Post-Processing": "Постобработка промпта",
|
||||
"Applies additional processing to the prompt before sending it to the API.": "Позволяет обработать промпт перед отправкой в API.",
|
||||
@ -1342,7 +1341,7 @@
|
||||
"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.",
|
||||
"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_Normal": "Обычная",
|
||||
"WI_Entry_Status_Vectorized": "Векторизованная",
|
||||
@ -1366,13 +1365,7 @@
|
||||
"Can be used to automatically activate Quick Replies": "Can be used to automatically activate Quick Replies",
|
||||
"Automation ID": "Automation ID",
|
||||
"( 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",
|
||||
"close": "close",
|
||||
"reset": "reset",
|
||||
"save": "save",
|
||||
"Open checkpoint chat": "Открыть чат из чекпоинта",
|
||||
@ -2035,5 +2028,121 @@
|
||||
"tags_sorting_desc": "Автоматически сортировать теги по алфавиту после создания или переименования одного из них.\nПри выключении новые теги будут просто добавляться в конец.\n\nЕсли вручную перетащить один из тегов на другое место, автосортировка отключится.",
|
||||
"Imported 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 сообщений.",
|
||||
"Non-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": "Закрыть"
|
||||
}
|
||||
|
@ -879,7 +879,7 @@
|
||||
"popup-button-no": "Немає",
|
||||
"popup-button-cancel": "Скасувати",
|
||||
"popup-button-import": "Імпорт",
|
||||
"Advanced Defininitions": "Розширені визначення",
|
||||
"Advanced Definitions": "Розширені визначення",
|
||||
"Prompt Overrides": "Перевизначення підказок",
|
||||
"(For Chat Completion and Instruct Mode)": "(Для завершення чату та режиму інструктажу)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Вставте {{original}} в будь-яке поле, щоб включити відповідний запит з налаштувань системи.",
|
||||
|
@ -879,7 +879,7 @@
|
||||
"popup-button-no": "KHÔNG",
|
||||
"popup-button-cancel": "Hủy",
|
||||
"popup-button-import": "Nhập",
|
||||
"Advanced Defininitions": "Các Định nghĩa Nâng cao",
|
||||
"Advanced Definitions": "Các Định nghĩa Nâng cao",
|
||||
"Prompt Overrides": "Ghi đè Prompt",
|
||||
"(For Chat Completion and Instruct Mode)": "(Đối với chế độ hoàn thành trò chuyện và hướng dẫn)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "Chèn {{original}} vào bất kỳ hộp nào để bao gồm Prompt mặc định tương ứng từ cài đặt hệ thống.",
|
||||
|
@ -78,7 +78,7 @@
|
||||
"Allow": "Allow",
|
||||
"Forbid": "Forbid",
|
||||
"Enable OpenAI completion streaming": "启用OpenAI文本补全流式传输",
|
||||
"Display the response bit by bit as it is generated.": "随着回复的生成,逐位显示结果。",
|
||||
"Display the response bit by bit as it is generated.": "随着回复的生成,逐词逐句地显示结果。",
|
||||
"When this is off, responses will be displayed all at once when they are complete.": "当此选项关闭时,回复将在完成后一次性显示。",
|
||||
"Frequency Penalty": "频率惩罚",
|
||||
"Presence Penalty": "存在惩罚",
|
||||
@ -185,13 +185,13 @@
|
||||
"Mirostat Eta": "Mirostat η",
|
||||
"Learning rate of Mirostat": "Mirostat 的学习率。",
|
||||
"Beam search": "束搜索",
|
||||
"A greedy, brute-force algorithm used in LLM sampling to find the most likely sequence of words or tokens. It expands multiple candidate sequences at once, maintaining a fixed number (beam width) of top sequences at each step.": "A greedy, brute-force algorithm used in LLM sampling to find the most likely sequence of words or tokens. It expands multiple candidate sequences at once, maintaining a fixed number (beam width) of top sequences at each step.",
|
||||
"# of Beams": "# of Beams",
|
||||
"A greedy, brute-force algorithm used in LLM sampling to find the most likely sequence of words or tokens. It expands multiple candidate sequences at once, maintaining a fixed number (beam width) of top sequences at each step.": "一种在LLM采样中使用的贪婪暴力算法,用于找到最可能的单词或标记序列。它一次扩展多个候选序列,在每一步保留固定数量(光束宽度)的最佳序列。",
|
||||
"# of Beams": "光束数量",
|
||||
"The number of sequences generated at each step with Beam Search.": "The number of sequences generated at each step with Beam Search.",
|
||||
"Length Penalty": "长度惩罚",
|
||||
"Penalize sequences based on their length.": "Penalize sequences based on their length.",
|
||||
"Early Stopping": "提前停止",
|
||||
"Controls the stopping condition for beam search. If checked, the generation stops as soon as there are '# of Beams' sequences. If not checked, a heuristic is applied and the generation is stopped when it's very unlikely to find better candidates.": "Controls the stopping condition for beam search. If checked, the generation stops as soon as there are '# of Beams' sequences. If not checked, a heuristic is applied and the generation is stopped when it's very unlikely to find better candidates.",
|
||||
"Controls the stopping condition for beam search. If checked, the generation stops as soon as there are '# of Beams' sequences. If not checked, a heuristic is applied and the generation is stopped when it's very unlikely to find better candidates.": "控制光束搜索的停止条件。勾选时,当生成到达‘光束数量’的序列时停止。如果未勾选,则采用启发式方法,当几乎不可能找到更好的候选项时停止生成。",
|
||||
"Contrastive search": "对比搜索",
|
||||
"Contrastive_search_txt": "通过利用大多数 LLM 表示空间的各向同性以鼓励多样性同时保持一致性的采样器。详见 Su 等人在 2022 年发表的论文 《A Contrastive Framework for Neural Text Generation》。",
|
||||
"Penalty Alpha": "惩罚系数 α",
|
||||
@ -208,7 +208,7 @@
|
||||
"Speculative Ngram": "推测性 Ngram",
|
||||
"Use a different speculative decoding method without a draft model": "使用不同的推测解码方法(不采用草稿模型)。最好使用草稿模型。推测性 Ngram 的效果不太好。",
|
||||
"Spaces Between Special Tokens": "特殊词符之间的空格",
|
||||
"Seed_desc": "A random seed to use for deterministic and reproducable outputs. Set to -1 to use a random seed.",
|
||||
"Seed_desc": "一个用于生成确定性和可复现的输出的随机种子。设置为 -1 时会使用随机种子。",
|
||||
"LLaMA / Mistral / Yi models only": "LLaMA / Mistral / Yi模型专用。首先确保您选择了适当的词符化器。\n这项设置决定了你不想在结果中看到的字符串。\n每行一个字符串。可以是文本或者[词符id]。\n许多词符以空格开头。如果不确定,请使用词符计数器。",
|
||||
"Example: some text [42, 69, 1337]": "例如:\n一些文本\n[42, 69, 1337]",
|
||||
"CFG": "CFG",
|
||||
@ -227,8 +227,8 @@
|
||||
"llama.cpp only. Determines the order of samplers. If Mirostat mode is not 0, sampler order is ignored.": "仅限 llama.cpp。确定采样器的顺序。如果 Mirostat 模式不为 0,则忽略采样器顺序。",
|
||||
"Sampler Priority": "采样器优先级",
|
||||
"Ooba only. Determines the order of samplers.": "确定采样器的顺序(仅适用于Ooba)",
|
||||
"Aphrodite only. Determines the order of samplers. Skew is always applied post-softmax, so it's not included here.": "Aphrodite only. Determines the order of samplers. Skew is always applied post-softmax, so it's not included here.",
|
||||
"Aphrodite only. Determines the order of samplers.": "Aphrodite only. Determines the order of samplers.",
|
||||
"Aphrodite only. Determines the order of samplers. Skew is always applied post-softmax, so it's not included here.": "仅适用于 Aphrodite,用于确定采样器的顺序。偏移(Skew)始终在 softmax 后应用,因此不包含在这里。",
|
||||
"Aphrodite only. Determines the order of samplers.": "仅适用于 Aphrodite。用于确定采样器的顺序。",
|
||||
"Character Names Behavior": "角色名称行为",
|
||||
"Helps the model to associate messages with characters.": "有助于模型将消息与角色关联起来。",
|
||||
"None": "无",
|
||||
@ -266,13 +266,15 @@
|
||||
"Use system prompt": "使用系统提示词",
|
||||
"Merges_all_system_messages_desc_1": "合并所有系统消息,直到第一条具有非系统角色的消息,然后通过",
|
||||
"Merges_all_system_messages_desc_2": "字段发送。",
|
||||
"Show model thoughts": "展示思维链",
|
||||
"Display the model's internal thoughts in the response.": "展示模型在回复时的内部思维链。",
|
||||
"Assistant Prefill": "AI预填",
|
||||
"Expand the editor": "展开编辑器",
|
||||
"Start Claude's answer with...": "以如下内容开始Claude的回答...",
|
||||
"Assistant Impersonation Prefill": "AI帮答预填",
|
||||
"Use system prompt (Claude 2.1+ only)": "使用系统提示词(仅适用于Claude 2.1+)",
|
||||
"Send the system prompt for supported models. If disabled, the user message is added to the beginning of the prompt.": "为支持的模型发送系统提示词。如果禁用,则用户消息将添加到提示词的开头。",
|
||||
"Confirm token parsing with": "Confirm token parsing with",
|
||||
"Confirm token parsing with": "确认使用以下工具进行词符解析",
|
||||
"Tokenizer": "词符化器",
|
||||
"New preset": "新预设",
|
||||
"Delete preset": "删除预设",
|
||||
@ -316,9 +318,9 @@
|
||||
"Get your NovelAI API Key": "获取您的 NovelAI API 密钥",
|
||||
"Enter it in the box below": "在下面的框中输入",
|
||||
"Novel AI Model": "Novel AI 模型",
|
||||
"No connection...": "没有连接...",
|
||||
"No connection...": "无连接...",
|
||||
"API Type": "API 类型",
|
||||
"Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]": "Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]",
|
||||
"Generic (OpenAI-compatible) [LM Studio, LiteLLM, etc.]": "通用(兼容 OpenAI)[LM Studio、LiteLLM 等]",
|
||||
"TogetherAI API Key": "TogetherAI API 密钥",
|
||||
"TogetherAI Model": "TogetherAI 模型",
|
||||
"-- Connect to the API --": "-- 连接到API --",
|
||||
@ -350,7 +352,7 @@
|
||||
"All": "All",
|
||||
"class": "All Classes",
|
||||
"Toggle grid view": "切换网格视图",
|
||||
"No model description": "[No description]",
|
||||
"No model description": "[无描述]",
|
||||
"vllm-project/vllm": "vllm-project/vllm(OpenAI API 包装器模式)",
|
||||
"vLLM API key": "vLLM API 密钥",
|
||||
"Example: 127.0.0.1:8000": "示例:http://127.0.0.1:8000",
|
||||
@ -399,12 +401,12 @@
|
||||
"View API Usage Metrics": "查看API使用情况",
|
||||
"Follow": "按照",
|
||||
"these directions": "这些步骤",
|
||||
"to get your OpenAI API key.": "获取您的OpenAI API密钥。",
|
||||
"to get your OpenAI API key.": "获取您的 OpenAI API 密钥。",
|
||||
"Use Proxy password field instead. This input will be ignored.": "请使用“代理密码”字段。此输入将被忽略。",
|
||||
"OpenAI Model": "OpenAI 模型",
|
||||
"Bypass API status check": "绕过API状态检查",
|
||||
"Show External models (provided by API)": "显示外部模型(由API提供)",
|
||||
"Claude API Key": "Claude API Key",
|
||||
"Claude API Key": "Claude API 密钥",
|
||||
"Get your key from": "从以下位置获取您的密钥",
|
||||
"Anthropic's developer console": "Anthropic 开发者控制台",
|
||||
"Claude Model": "Claude 模型",
|
||||
@ -430,23 +432,28 @@
|
||||
"Groq Model": "Groq 模型",
|
||||
"NanoGPT API Key": "NanoGPT API Key",
|
||||
"NanoGPT Model": "NanoGPT Model",
|
||||
"DeepSeek API Key": "DeepSeek API 密钥",
|
||||
"DeepSeek Model": "DeepSeek 模型",
|
||||
"Perplexity API Key": "Perplexity API 密钥",
|
||||
"Perplexity Model": "Perplexity 模型",
|
||||
"Cohere API Key": "Cohere API 密钥",
|
||||
"Cohere Model": "Cohere 模型",
|
||||
"Block Entropy API Key": "Block Entropy API Key",
|
||||
"Select a Model": "Select a Model",
|
||||
"Custom Endpoint (Base URL)": "自定义端点(基本 URL)",
|
||||
"Block Entropy API Key": "Block Entropy API 密钥",
|
||||
"Select a Model": "选择一个模型",
|
||||
"Custom Endpoint (Base URL)": "自定义端点(基础 URL)",
|
||||
"Example: http://localhost:1234/v1": "例如:http://localhost:1234/v1",
|
||||
"at the end of the URL!": "到 URL 的末尾!",
|
||||
"Custom API Key": "自定义 API 密钥",
|
||||
"(Optional)": "(可选)",
|
||||
"Enter a Model ID": "输入模型名",
|
||||
"Example: gpt-3.5-turbo": "例如:gpt-3.5-turbo",
|
||||
"Example: gpt-4o": "例如:gpt-4o",
|
||||
"Available Models": "可用模型",
|
||||
"Prompt Post-Processing": "提示词后处理",
|
||||
"Applies additional processing to the prompt before sending it to the API.": "在将提示词发送到 API 之前对其进行额外处理。",
|
||||
"prompt_post_processing_none": "未选择",
|
||||
"prompt_post_processing_merge": "合并相同角色连续的发言",
|
||||
"prompt_post_processing_semi": "半严格(强制对话角色交替)",
|
||||
"prompt_post_processing_strict": "严格(强制对话角色交替、用户最先)",
|
||||
"01.AI API Key": "01.AI API密钥",
|
||||
"01.AI Model": "01.AI 模型",
|
||||
"Additional Parameters": "附加参数",
|
||||
@ -503,25 +510,25 @@
|
||||
"Never": "永不",
|
||||
"Groups and Past Personas": "Groups and Past Personas",
|
||||
"Always": "永远",
|
||||
"Instruct Sequences": "Instruct Sequences",
|
||||
"User Message Sequences": "User Message Sequences",
|
||||
"Instruct Sequences": "指令序列",
|
||||
"User Message Sequences": "用户消息序列",
|
||||
"Inserted before a User message and as a last prompt line when impersonating.": "插入到用户消息之前并作为模拟时的最后一行提示词。",
|
||||
"User Prefix": "用户消息前缀",
|
||||
"Inserted after a User message.": "插入到用户消息之后。",
|
||||
"User Suffix": "用户消息后缀",
|
||||
"Assistant Message Sequences": "Assistant Message Sequences",
|
||||
"Assistant Message Sequences": "助手消息序列",
|
||||
"Inserted before an Assistant message and as a last prompt line when generating an AI reply.": "插入到助手消息之前并作为生成 AI 回复时的最后一行提示词。",
|
||||
"Assistant Prefix": "助手消息前缀",
|
||||
"Inserted after an Assistant message.": "插入于助手消息之后。",
|
||||
"Assistant Suffix": "助手消息后缀",
|
||||
"System Message Sequences": "System Message Sequences",
|
||||
"System Message Sequences": "系统消息序列",
|
||||
"Inserted before a System (added by slash commands or extensions) message.": "插入到系统(由快捷命令或扩展添加)消息之前。",
|
||||
"System Prefix": "System Message Prefix",
|
||||
"System Prefix": "系统消息前缀",
|
||||
"Inserted after a System message.": "插入到系统消息之后。",
|
||||
"System Suffix": "System Message Suffix",
|
||||
"System Suffix": "系统消息后缀",
|
||||
"If enabled, System Sequences will be the same as User Sequences.": "如果启用,系统序列将与用户序列相同。",
|
||||
"System same as User": "系统与用户相同",
|
||||
"System Prompt Sequences": "System Prompt Sequences",
|
||||
"System Prompt Sequences": "系统提示词序列",
|
||||
"Inserted before a System prompt.": "插入到系统提示词之前。",
|
||||
"System Prompt Prefix": "系统提示词前缀",
|
||||
"Inserted after a System prompt.": "在系统提示词后插入。",
|
||||
@ -556,7 +563,7 @@
|
||||
"Token Padding": "词符填充",
|
||||
"Miscellaneous": "杂项",
|
||||
"Non-markdown strings": "非 Markdown 字符串",
|
||||
"comma delimited,no spaces between": "comma delimited,no spaces between",
|
||||
"comma delimited,no spaces between": "以逗号分隔,无需空格",
|
||||
"Start Reply With": "以...开始回复",
|
||||
"Show reply prefix in chat": "在聊天中显示回复前缀",
|
||||
"World Info": "世界信息",
|
||||
@ -688,8 +695,8 @@
|
||||
"Show Message Token Count": "显示消息词符数",
|
||||
"Single-row message input area. Mobile only, no effect on PC": "将输入框限制为一行。仅适用于移动设备,对PC无影响",
|
||||
"Compact Input Area (Mobile)": "紧凑输入区域(移动端)",
|
||||
"Display swipe numbers for all messages, not just the last.": "Display swipe numbers for all messages, not just the last.",
|
||||
"Swipe # for All Messages": "Swipe # for All Messages",
|
||||
"Display swipe numbers for all messages, not just the last.": "显示所有信息的滑动编号,而非仅限最后一条。",
|
||||
"Swipe # for All Messages": "给所有信息分配滑动编号 #",
|
||||
"In the Character Management panel, show quick selection buttons for favorited characters": "在角色管理面板中,显示快速选择按钮以选择收藏的角色",
|
||||
"Characters Hotswap": "角色卡热切换",
|
||||
"Enable magnification for zoomed avatar display.": "启用放大功能以放大头像显示。",
|
||||
@ -894,7 +901,7 @@
|
||||
"Favorite characters to add them to HotSwaps": "收藏角色以将它们添加到快速热切换区",
|
||||
"Token counts may be inaccurate and provided just for reference.": "词符计数可能不准确,仅供参考。",
|
||||
"Total tokens": "总词符数",
|
||||
"Calculating...": "正在计算…",
|
||||
"Calculating...": "正在计算...",
|
||||
"Tokens": "词符数",
|
||||
"Permanent tokens": "永久词符",
|
||||
"Permanent": "恒定的",
|
||||
@ -936,10 +943,10 @@
|
||||
"Chat Name (Optional)": "聊天名称(可选)",
|
||||
"Chat Lore": "聊天知识",
|
||||
"Click to select a new avatar for this group": "单击选择该群聊的新头像",
|
||||
"Group reply strategy": "群聊回复策略",
|
||||
"Group reply strategy": "群聊发言顺序",
|
||||
"Manual": "手动",
|
||||
"Natural order": "自然顺序",
|
||||
"List order": "上下顺序",
|
||||
"List order": "从上到下",
|
||||
"Group generation handling mode": "群组生成处理模式",
|
||||
"Swap character cards": "交换角色卡",
|
||||
"Join character cards (exclude muted)": "加入角色卡(不包括被禁言的)",
|
||||
@ -990,7 +997,7 @@
|
||||
"popup-button-import": "导入",
|
||||
"popup-button-crop": "裁剪",
|
||||
"Close popup": "关闭弹出窗口",
|
||||
"Advanced Defininitions": "高级定义",
|
||||
"Advanced Definitions": "高级定义",
|
||||
"Prompt Overrides": "提示词覆盖",
|
||||
"(For Chat Completion and Instruct Mode)": "(用于聊天补全和指导模式)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "将{{original}}插入到任一框中,以包含系统设置中的相应默认提示词。",
|
||||
@ -1023,7 +1030,7 @@
|
||||
"Chatty": "高",
|
||||
"Examples of dialogue": "对话示例",
|
||||
"Important to set the character's writing style.": "设置角色的写作风格,很重要!",
|
||||
"(Examples of chat dialog. Begin each example with START on a new line.)": "(聊天对话的示例,每个示例都另起一行以<START>开头。)",
|
||||
"(Examples of chat dialog. Begin each example with START on a new line.)": "(聊天对话的示例,每个示例都另起一行以<START>开头。)",
|
||||
"Save": "保存",
|
||||
"Chat History": "聊天记录",
|
||||
"Import Chat": "导入聊天",
|
||||
@ -1107,12 +1114,15 @@
|
||||
"A relative likelihood of entry activation within the group": "组内进入激活的相对可能性",
|
||||
"Group Weight": "组权重",
|
||||
"Sticky entries will stay active for N messages after being triggered.": "粘性条目在被触发后将保持活跃状态 N 条消息。",
|
||||
"Sticky": "粘性",
|
||||
"Sticky": "黏性",
|
||||
"Non-sticky": "无黏性",
|
||||
"Entries with a cooldown can't be activated N messages after being triggered.": "具有冷却时间的条目在触发后 N 条消息内无法被激活。",
|
||||
"Cooldown": "冷却",
|
||||
"No cooldown": "无冷却",
|
||||
"Entries with a delay can't be activated until there are N messages present in the chat.": "直到聊天中出现 N 条消息时,延迟的条目才能被激活。",
|
||||
"Delay": "延迟",
|
||||
"Filter to Characters or Tags": "应用到角色或标签",
|
||||
"No delay": "无延迟",
|
||||
"Filter to Characters or Tags": "绑定到角色或标签",
|
||||
"Switch the Character/Tags filter around to exclude the listed characters and tags from matching for this entry": "切换角色/标签筛选方式,将列出的角色和标签排除在匹配范围之外",
|
||||
"Exclude": "排除",
|
||||
"-- Characters not found --": "-- 未找到角色 --",
|
||||
@ -1132,8 +1142,8 @@
|
||||
"prompt_manager_relative": "相对",
|
||||
"prompt_manager_in_chat": "聊天中",
|
||||
"prompt_manager_depth": "深度",
|
||||
"Injection depth. 0 = after the last message, 1 = before the last message, etc.": "注入深度。0 = 在最后一条消息之后,1 = 在最后一条消息之前,等等。",
|
||||
"The content of this prompt is pulled from elsewhere and cannot be edited here.": "The content of this prompt is pulled from elsewhere and cannot be edited here.",
|
||||
"Injection depth. 0 = after the last message, 1 = before the last message, etc.": "注入深度。“0”为在最后一条消息之后,“1”为在最后一条消息之前,等等。",
|
||||
"The content of this prompt is pulled from elsewhere and cannot be edited here.": "此提示词的内容是从其他地方提取的,无法在此处进行编辑。",
|
||||
"Prompt": "提示词",
|
||||
"The prompt to be sent.": "要发送的提示词。",
|
||||
"This prompt cannot be overridden by character cards, even if overrides are preferred.": "即使选择覆盖,此提示词也不能被角色卡覆盖。",
|
||||
@ -1194,7 +1204,7 @@
|
||||
"alternate_greetings_hint_1": "点击",
|
||||
"alternate_greetings_hint_2": "按钮即可开始!",
|
||||
"Alternate Greeting #": "额外问候语 #",
|
||||
"(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)": "(这是每次聊天开始时角色的第一条消息)",
|
||||
"View contents": "查看内容",
|
||||
"Remove the file": "删除文件",
|
||||
"Author's Note": "作者注释",
|
||||
@ -1207,7 +1217,7 @@
|
||||
"Insertion Frequency": "插入频率",
|
||||
"(0 = Disable, 1 = Always)": "(“0”为禁用,“1”为始终)",
|
||||
"User inputs until next insertion:": "用户输入直到下一次插入:",
|
||||
"Character Author's Note (Private)": "人物作者注(私有)",
|
||||
"Character Author's Note (Private)": "人物作者注(私密)",
|
||||
"Won't be shared with the character card on export.": "导出时不会与角色卡共享。",
|
||||
"Will be automatically added as the author's note for this character. Will be used in groups, but can't be modified when a group chat is open.": "会自动添加为该角色的作者注解,在群聊中使用,但群聊开启时无法修改。",
|
||||
"Use character author's note": "使用角色作者的注释",
|
||||
@ -1234,9 +1244,9 @@
|
||||
"Insertion Depth:": "插入深度:",
|
||||
"Token Probabilities": "词符概率",
|
||||
"Select a token to see alternatives considered by the AI.": "选择一个词符来查看 AI 考虑的替代方案。",
|
||||
"Reroll with the entire prefix": "Reroll with the entire prefix",
|
||||
"Reroll with the entire prefix": "使用完整前缀重新生成",
|
||||
"Not connected to API!": "未连接到API!",
|
||||
"Type a message, or /? for help": "键入消息,或 /? 获取帮助",
|
||||
"Type a message, or /? for help": "输入想发送的消息,或输入 /? 获取帮助",
|
||||
"Continue script execution": "继续执行脚本",
|
||||
"Pause script execution": "暂停执行脚本",
|
||||
"Abort script execution": "中止执行脚本",
|
||||
@ -1355,7 +1365,7 @@
|
||||
"You are in offline mode. Click on the image below to set the expression.": "您处于离线模式。点击下方图片即可设置表情。",
|
||||
"Sprite Folder Override": "表情文件夹覆盖",
|
||||
"Use a forward slash to specify a subfolder. Example: _space": "使用正斜杠指定子文件夹。例如:",
|
||||
"Upload sprite pack (ZIP)": "上传表情包 (ZIP)",
|
||||
"Upload sprite pack (ZIP)": "上传表情包(ZIP)",
|
||||
"Remove all image overrides": "删除所有图片覆盖",
|
||||
"Create new folder in the _space": "创建新文件夹到",
|
||||
"folder of your user data directory and name it as the name of the character.": "用户数据目录的文件夹并将其命名为角色的名称。",
|
||||
@ -1460,12 +1470,12 @@
|
||||
"ext_regex_global_scripts": "全局正则脚本",
|
||||
"ext_regex_global_scripts_desc": "影响所有角色,保存在本地设定中",
|
||||
"ext_regex_scoped_scripts": "局部正则脚本",
|
||||
"ext_regex_disallow_scoped": "Disallow using scoped regex",
|
||||
"ext_regex_allow_scoped": "允许使用范围正则表达式",
|
||||
"ext_regex_disallow_scoped": "不允许使用局部正则",
|
||||
"ext_regex_allow_scoped": "允许使用局部正则",
|
||||
"ext_regex_scoped_scripts_desc": "只影响当前角色,保存在角色卡片中",
|
||||
"Regex Editor": "正则表达式编辑器",
|
||||
"Test Mode": "测试模式",
|
||||
"ext_regex_desc": "正则是一款使用正则表达式查找/替换字符串的工具。如果您想了解更多信息,请点击标题旁边的 ?。",
|
||||
"ext_regex_desc": "“正则”是一个使用“正则表达式”来查找/替换字符串的工具。如果您想了解更多信息,请点击标题旁边的“?”。",
|
||||
"Input": "输入",
|
||||
"ext_regex_test_input_placeholder": "在此输入...",
|
||||
"Output": "输出",
|
||||
@ -1566,7 +1576,7 @@
|
||||
"Click to set": "点击设置",
|
||||
"You can find your API key in the Stability AI dashboard.": "您可以在 Stability AI 仪表板中找到您的 API 密钥。",
|
||||
"Style Preset": "风格预设",
|
||||
"Prompt Upsampling": "Prompt Upsampling",
|
||||
"Prompt Upsampling": "提示词增强(Upsampling)",
|
||||
"Sampling method": "采样方法",
|
||||
"Scheduler": "调度器",
|
||||
"Resolution": "分辨率",
|
||||
@ -1584,7 +1594,7 @@
|
||||
"Karras": "Karras",
|
||||
"Not all samplers supported.": "并非所有采样器都受支持。",
|
||||
"sd_adetailer_face": "Use ADetailer with face model during the generation. The ADetailer extension must be installed on the backend.",
|
||||
"Use ADetailer (Face)": "使用 ADetailer (Face)",
|
||||
"Use ADetailer (Face)": "使用 ADetailer(脸部)",
|
||||
"SMEA versions of samplers are modified to perform better at high resolution.": "SMEA 版本的采样器经过修改,在高分辨率下性能更佳。",
|
||||
"SMEA": "中小企业协会",
|
||||
"DYN variants of SMEA samplers often lead to more varied output, but may fail at very high resolutions.": "SMEA 采样器的 DYN 变体通常会产生更加多样化的输出,但在非常高的分辨率下可能会失败。",
|
||||
@ -1627,9 +1637,9 @@
|
||||
"Select TTS Provider": "选择 文本转语音 的服务提供商",
|
||||
"tts_enabled": "已启用",
|
||||
"Narrate user messages": "朗读用户消息",
|
||||
"Auto Generation": "Auto Generation",
|
||||
"Requires auto generation to be enabled.": "Requires auto generation to be enabled.",
|
||||
"Narrate by paragraphs (when streaming)": "Narrate by paragraphs (when streaming)",
|
||||
"Auto Generation": "自动生成",
|
||||
"Requires auto generation to be enabled.": "需要启用自动生成功能。",
|
||||
"Narrate by paragraphs (when streaming)": "按段朗读(流式播放时)",
|
||||
"Only narrate quotes": "只朗读引号内文本",
|
||||
"Ignore text, even quotes, inside asterisk": "不朗读所有*星号内文本*,即使其被引号包裹",
|
||||
"Narrate only the translated text": "只朗读翻译后文本",
|
||||
@ -1658,9 +1668,9 @@
|
||||
"Enable for files": "为文件启用",
|
||||
"Translate files into English before processing": "处理之前将文件翻译成英文",
|
||||
"Message attachments": "消息附件",
|
||||
"Size threshold (KB)": "大小阈值 (KB)",
|
||||
"Size threshold (KB)": "大小阈值(KB)",
|
||||
"Chunk size (chars)": "块大小(字符)",
|
||||
"Chunk overlap (%)": "块重叠 (%)",
|
||||
"Chunk overlap (%)": "块重叠(%)",
|
||||
"Retrieve chunks": "检索块",
|
||||
"Data Bank files": "数据库文件",
|
||||
"Injection Template": "注入模板",
|
||||
@ -1691,6 +1701,7 @@
|
||||
"This will create a new subfolder...": "这将在 /data/ 目录中创建一个新的子文件夹,以用户的句柄作为文件夹名称。",
|
||||
"Note:": "提示:",
|
||||
"this chat is temporary and will be deleted as soon as you leave it.": "此聊天会话是临时的,会在你离开时被删除。",
|
||||
"Enter a new display name:": "输入一个新的昵称:",
|
||||
"Current Password:": "当前密码:",
|
||||
"New Password:": "新密码:",
|
||||
"Confirm New Password:": "确认新密码:",
|
||||
@ -1711,22 +1722,25 @@
|
||||
"chat_rename_1": "输入聊天的新名称:",
|
||||
"chat_rename_2": "注意!!使用已有文件名会导致错误!!",
|
||||
"chat_rename_3": "此举会将次聊天与标记为“检查点”的聊天解绑。",
|
||||
"chat_rename_4": "不需要在结尾添加 '.jsonl'",
|
||||
"chat_rename_4": "不需要在结尾添加 '.JSONL'",
|
||||
"Enter Checkpoint Name:": "输入检查点名称:",
|
||||
"(Leave empty to auto-generate)": "(留空以自动生成)",
|
||||
"The currently existing checkpoint will be unlinked and replaced with the new checkpoint, but can still be found in the Chat Management.": "当前检查点将会被解绑并替换为新的检查点,但仍可在聊天管理中找到。",
|
||||
"Include Body Parameters": "包括主体参数",
|
||||
"custom_include_body_desc": "聊天完成请求主体中要包含的参数(YAML 对象)\n\n示例:\n- top_k:20\n- repetition_penalty:1.1",
|
||||
"Exclude Body Parameters": "排除主体参数",
|
||||
"custom_exclude_body_desc": "要从聊天完成请求主体中排除的参数(YAML 数组)\n\n示例:\n- frequency_penalty\n- presence_penalty",
|
||||
"Include Request Headers": "包含请求标头",
|
||||
"custom_include_headers_desc": "聊天完成请求的附加标头(YAML 对象)\n\n示例:\n- CustomHeader:自定义值\n- AnotherHeader:自定义值",
|
||||
"Debug Warning": "此类别中的功能仅供高级用户使用。如果您不确定后果,请不要点击任何内容。",
|
||||
"Functions in this category are for advanced users only. Don't click anything if you're not sure about the consequences.": "此类别中的功能仅供高级用户使用。如果您不确定后果,请不要点击任何内容。",
|
||||
"THIS IS PERMANENT!": "此操作不可逆!",
|
||||
"Also delete the chat files": "同时删除聊天文件",
|
||||
"Are you sure you want to delete this user?": "您确定要删除该用户吗?",
|
||||
"Deleting:": "删除:",
|
||||
"Also wipe user data.": "也清空用户数据。",
|
||||
"Also wipe user data.": "同时清空用户数据",
|
||||
"Warning:": "警告:",
|
||||
"This action is irreversible.": "此操作不可逆。",
|
||||
"Type the user's handle below to confirm:": "在下面输入用户的名称以确认:",
|
||||
"Type the user's handle below to confirm:": "在下面输入此用户的用户句柄以确认删除操作:",
|
||||
"Are you sure you want to duplicate this character?": "你确定要复制这个角色吗?",
|
||||
"If you just want to start a new chat with the same character...": "如果你只是想要与此角色开启一个新的聊天,只需点击聊天左下方菜单中的“开始新聊天”按钮。",
|
||||
"Forbid Media Override explanation": "当前角色/群聊成员使用外部媒体的能力。",
|
||||
@ -1764,11 +1778,11 @@
|
||||
"help_format_26": "内联代码",
|
||||
"help_format_27": "> 文本",
|
||||
"help_format_28": "显示为块引用(请注意 > 后面的空格)",
|
||||
"help_format_29": "# 文本",
|
||||
"help_format_29": "# 文本",
|
||||
"help_format_30": "显示为大标题(注意空格)",
|
||||
"help_format_32": "## 文本",
|
||||
"help_format_32": "## 文本",
|
||||
"help_format_33": "显示为中等标题(注意空格)",
|
||||
"help_format_35": "### 文本",
|
||||
"help_format_35": "### 文本",
|
||||
"help_format_36": "显示为小标题(注意空格)",
|
||||
"help_1": "您好!请选择您想要详细了解的帮助主题:",
|
||||
"help_2": "斜线命令",
|
||||
@ -1821,9 +1835,27 @@
|
||||
"char_import_8": "RisuRealm 角色(直链)",
|
||||
"Supports importing multiple characters.": "支持导入多个角色。",
|
||||
"Write each URL or ID into a new line.": "将每个 URL 或 ID 写入新行。",
|
||||
"Show Raw Prompt": "显示原始提示",
|
||||
"Copy Prompt": "复制提示",
|
||||
"Show Prompt Differences": "显示提示差异",
|
||||
"Enter the Git URL of the extension to install": "输入扩展程序的 Git URL 以安装",
|
||||
"Disclaimer:": "免责声明:",
|
||||
"Please be aware that using external extensions can have unintended side effects and may pose security risks. Always make sure you trust the source before importing an extension. We are not responsible for any damage caused by third-party extensions.": "使用外部的扩展程序可能存在意料外的副作用和安全隐患。在导入扩展程序前,请一定确认其来源可信。我们不为第三方扩展程序造成的任何损失负责。",
|
||||
"Prompt Itemization": "将提示词分条",
|
||||
"Show Raw Prompt": "显示原始提示词",
|
||||
"Copy Prompt": "复制提示词",
|
||||
"Show Prompt Differences": "显示提示词差异",
|
||||
"API/Model:": "API/模型:",
|
||||
"Preset:": "预设:",
|
||||
"Tokenizer:": "分词器:",
|
||||
"Only the white numbers really matter. All numbers are estimates. Grey color items may not have been included in the context due to certain prompt format settings.": "只有白色的数字作数。所有数字均为估算。\n 灰色的数字可能因特定的提示词处理规则而被排除在外。",
|
||||
"System Info:": "系统信息:",
|
||||
"Prompt Tokens:": "提示词Token:",
|
||||
"World Info:": "世界书:",
|
||||
"Chat History:": "聊天记录:",
|
||||
"Extensions:": "扩展程序:",
|
||||
"Bias:": "Bias:",
|
||||
"Total Tokens in Prompt:": "提示词的总Token数量:",
|
||||
"Max Context": "最大上下文:",
|
||||
"(Context Size - Response Length)": "(上下文长度 - 回复长度)",
|
||||
":": ":",
|
||||
"System-wide Replacement Macros (in order of evaluation):": "系统范围的替换宏(按评估顺序):",
|
||||
"help_macros_1": "仅适用于斜线命令批处理。替换为上一个命令的返回结果。",
|
||||
"help_macros_2": "仅插入一个换行符。",
|
||||
@ -1913,7 +1945,9 @@
|
||||
"help_macros_68": "替换为全局变量“name”的值减 1 的结果",
|
||||
"help_macros_69": "替换为范围变量“name”的值",
|
||||
"help_macros_70": "用范围变量“name”的索引处的项目值(对于数组/列表或对象/字典)替换",
|
||||
"Choose what to export": "选择您想要导出什么:",
|
||||
"{{name}}": "{{name}}",
|
||||
"Choose what to import": "选择您想要导入什么:",
|
||||
"If necessary, you can later restore this chat file from the /backups folder": "若需要,您可稍后在 /backups 文件夹中恢复此聊天文件。",
|
||||
"Also delete the current chat file": "同时删除当前聊天文件",
|
||||
"Persona Lorebook for": "Persona Lorebook for",
|
||||
@ -1938,8 +1972,13 @@
|
||||
"If you have sufficient credits, please try again later.": "若您有足够的余额,请稍后再试。",
|
||||
"Are you sure you want to reset your settings to factory defaults?": "您确定要将您的设置重置为出厂默认设置吗?",
|
||||
"Don't forget to save a snapshot of your settings before proceeding.": "在继续之前,不要忘记保存您的设置快照。",
|
||||
"Enter your password below to confirm:": "输入您的密码以确认:",
|
||||
"Chat Scenario Override": "聊天场景覆盖",
|
||||
"Remove": "移除",
|
||||
"Unique to this chat.": "Unique to this chat.",
|
||||
"All group members will use the following scenario text instead of what is specified in their character cards.": "All group members will use the following scenario text instead of what is specified in their character cards.",
|
||||
"The following scenario text will be used instead of the value set in the character card.": "The following scenario text will be used instead of the value set in the character card.",
|
||||
"Checkpoints inherit the scenario override from their parent, and can be changed individually after that.": "Checkpoints inherit the scenario override from their parent, and can be changed individually after that.",
|
||||
"Settings Snapshots": "设置快照",
|
||||
"Record a snapshot of your current settings.": "记录当前设置的快照。",
|
||||
"Make a Snapshot": "制作快照",
|
||||
@ -1962,6 +2001,7 @@
|
||||
"Click on the folder icon to use this tag as a folder.": "点击文件夹图标来将此标签作为一个文件夹。",
|
||||
"Use alphabetical sorting": "按字母顺序排列",
|
||||
"tags_sorting_desc": "启用后,标签在创建或重命名时会自动按字母顺序排序。\n禁用后,新标签会追加到末尾。\n\n如果通过拖动手动重新排列标签,则自动排序将被禁用。",
|
||||
"Are you sure you want to delete the theme?": "你确定要删除这个主题吗?",
|
||||
"Hi,": "嗨,",
|
||||
"To enable multi-account features, restart the SillyTavern server with": "要启用多帐户功能,请使用以下命令重新启动 SillyTavern 服务器",
|
||||
"set to true in the config.yaml file.": "在 config.yaml 文件中设置为 true。",
|
||||
@ -1982,6 +2022,8 @@
|
||||
"Reset Settings": "重置设置",
|
||||
"Wipe all user data and reset your account to factory settings.": "删除所有用户数据并将您的账号重置为默认设置。",
|
||||
"Reset Everything": "重置一切",
|
||||
"This will delete all your settings and data. There will be no undo button. Make sure you have a backup before proceeding.": "This will delete all your settings and data. There will be no undo button.\n Make sure you have a backup before proceeding.",
|
||||
"Account reset code has been posted to the server console.": "Account reset code has been posted to the server console.",
|
||||
"Reset Code:": "重置代码:",
|
||||
"Want to update?": "获取最新版本",
|
||||
"How to start chatting?": "如何快速开始聊天?",
|
||||
|
@ -880,7 +880,7 @@
|
||||
"popup-button-no": "取消",
|
||||
"popup-button-cancel": "關閉",
|
||||
"popup-button-import": "匯入",
|
||||
"Advanced Defininitions": "- 進階定義",
|
||||
"Advanced Definitions": "- 進階定義",
|
||||
"Prompt Overrides": "提示詞覆寫",
|
||||
"(For Chat Completion and Instruct Mode)": "(用於聊天補全和指令模式)",
|
||||
"Insert {{original}} into either box to include the respective default prompt from system settings.": "在任一框中插入 {{original}} 以包含系統設定中的預設提示詞。",
|
||||
@ -1454,7 +1454,7 @@
|
||||
"Any contents here will replace the default Post-History Instructions used for this character. (v2 specpost_history_instructions)": "此處填入的內容將取代該角色的默認聊天歷史後指示(Post-History Instructions)。\n(v2 格式:specpost_history_instructions)",
|
||||
"comma delimited,no spaces between": "逗號分割,無需空格",
|
||||
"e.g. black-forest-labs/FLUX.1-dev": "例如:black-forest-labs/FLUX.1-dev",
|
||||
"Example: gpt-3.5-turbo": "例如:gpt-3.5-turbo",
|
||||
"Example: gpt-4o": "例如:gpt-4o",
|
||||
"Example: http://localhost:1234/v1": "例如:http://localhost:1234/v1",
|
||||
"popup-button-crop": "裁剪",
|
||||
"(disabled when max recursion steps are used)": "(當最大遞歸步驟數使用時將停用)",
|
||||
|
156
public/script.js
156
public/script.js
@ -574,7 +574,7 @@ export const DEFAULT_SAVE_EDIT_TIMEOUT = debounce_timeout.relaxed;
|
||||
/** @type {debounce_timeout} The debounce timeout used for printing. debounce_timeout.quick: 100 ms */
|
||||
export const DEFAULT_PRINT_TIMEOUT = debounce_timeout.quick;
|
||||
|
||||
export const saveSettingsDebounced = debounce(() => saveSettings(), DEFAULT_SAVE_EDIT_TIMEOUT);
|
||||
export const saveSettingsDebounced = debounce((loopCounter = 0) => saveSettings(loopCounter), DEFAULT_SAVE_EDIT_TIMEOUT);
|
||||
export const saveCharacterDebounced = debounce(() => $('#create_button').trigger('click'), DEFAULT_SAVE_EDIT_TIMEOUT);
|
||||
|
||||
/**
|
||||
@ -2724,7 +2724,7 @@ export function getStoppingStrings(isImpersonate, isContinue) {
|
||||
export async function generateQuietPrompt(quiet_prompt, quietToLoud, skipWIAN, quietImage = null, quietName = null, responseLength = null, force_chid = null) {
|
||||
console.log('got into genQuietPrompt');
|
||||
const responseLengthCustomized = typeof responseLength === 'number' && responseLength > 0;
|
||||
let originalResponseLength = -1;
|
||||
let eventHook = () => {};
|
||||
try {
|
||||
/** @type {GenerateOptions} */
|
||||
const options = {
|
||||
@ -2736,11 +2736,15 @@ export async function generateQuietPrompt(quiet_prompt, quietToLoud, skipWIAN, q
|
||||
quietName: quietName,
|
||||
force_chid: force_chid,
|
||||
};
|
||||
originalResponseLength = responseLengthCustomized ? saveResponseLength(main_api, responseLength) : -1;
|
||||
if (responseLengthCustomized) {
|
||||
TempResponseLength.save(main_api, responseLength);
|
||||
eventHook = TempResponseLength.setupEventHook(main_api);
|
||||
}
|
||||
return await Generate('quiet', options);
|
||||
} finally {
|
||||
if (responseLengthCustomized) {
|
||||
restoreResponseLength(main_api, originalResponseLength);
|
||||
if (responseLengthCustomized && TempResponseLength.isCustomized()) {
|
||||
TempResponseLength.restore(main_api);
|
||||
TempResponseLength.removeEventHook(main_api, eventHook);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -3384,9 +3388,9 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy
|
||||
|
||||
const abortController = new AbortController();
|
||||
const responseLengthCustomized = typeof responseLength === 'number' && responseLength > 0;
|
||||
let originalResponseLength = -1;
|
||||
const isInstruct = power_user.instruct.enabled && api !== 'openai' && api !== 'novel' && !instructOverride;
|
||||
const isQuiet = true;
|
||||
let eventHook = () => {};
|
||||
|
||||
if (systemPrompt) {
|
||||
systemPrompt = substituteParams(systemPrompt);
|
||||
@ -3400,7 +3404,9 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy
|
||||
prompt = isInstruct ? (prompt + formatInstructModePrompt(name2, false, '', name1, name2, isQuiet, quietToLoud)) : (prompt + '\n');
|
||||
|
||||
try {
|
||||
originalResponseLength = responseLengthCustomized ? saveResponseLength(api, responseLength) : -1;
|
||||
if (responseLengthCustomized) {
|
||||
TempResponseLength.save(api, responseLength);
|
||||
}
|
||||
let generateData = {};
|
||||
|
||||
switch (api) {
|
||||
@ -3413,20 +3419,24 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy
|
||||
const koboldSettings = koboldai_settings[koboldai_setting_names[preset_settings]];
|
||||
generateData = getKoboldGenerationData(prompt, koboldSettings, amount_gen, max_context, isHorde, 'quiet');
|
||||
}
|
||||
TempResponseLength.restore(api);
|
||||
break;
|
||||
case 'novel': {
|
||||
const novelSettings = novelai_settings[novelai_setting_names[nai_settings.preset_settings_novel]];
|
||||
generateData = getNovelGenerationData(prompt, novelSettings, amount_gen, false, false, null, 'quiet');
|
||||
TempResponseLength.restore(api);
|
||||
break;
|
||||
}
|
||||
case 'textgenerationwebui':
|
||||
generateData = getTextGenGenerationData(prompt, amount_gen, false, false, null, 'quiet');
|
||||
TempResponseLength.restore(api);
|
||||
break;
|
||||
case 'openai': {
|
||||
generateData = [{ role: 'user', content: prompt.trim() }];
|
||||
if (systemPrompt) {
|
||||
generateData.unshift({ role: 'system', content: systemPrompt.trim() });
|
||||
}
|
||||
eventHook = TempResponseLength.setupEventHook(api);
|
||||
} break;
|
||||
}
|
||||
|
||||
@ -3468,41 +3478,100 @@ export async function generateRaw(prompt, api, instructOverride, quietToLoud, sy
|
||||
|
||||
return message;
|
||||
} finally {
|
||||
if (responseLengthCustomized) {
|
||||
restoreResponseLength(api, originalResponseLength);
|
||||
if (responseLengthCustomized && TempResponseLength.isCustomized()) {
|
||||
TempResponseLength.restore(api);
|
||||
TempResponseLength.removeEventHook(api, eventHook);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Temporarily change the response length for the specified API.
|
||||
* @param {string} api API to use.
|
||||
* @param {number} responseLength Target response length.
|
||||
* @returns {number} The original response length.
|
||||
*/
|
||||
function saveResponseLength(api, responseLength) {
|
||||
let oldValue = -1;
|
||||
if (api === 'openai') {
|
||||
oldValue = oai_settings.openai_max_tokens;
|
||||
oai_settings.openai_max_tokens = responseLength;
|
||||
} else {
|
||||
oldValue = amount_gen;
|
||||
amount_gen = responseLength;
|
||||
}
|
||||
return oldValue;
|
||||
}
|
||||
class TempResponseLength {
|
||||
static #originalResponseLength = -1;
|
||||
static #lastApi = null;
|
||||
|
||||
/**
|
||||
* Restore the original response length for the specified API.
|
||||
* @param {string} api API to use.
|
||||
* @param {number} responseLength Target response length.
|
||||
* @returns {void}
|
||||
*/
|
||||
function restoreResponseLength(api, responseLength) {
|
||||
if (api === 'openai') {
|
||||
oai_settings.openai_max_tokens = responseLength;
|
||||
} else {
|
||||
amount_gen = responseLength;
|
||||
static isCustomized() {
|
||||
return this.#originalResponseLength > -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the current response length for the specified API.
|
||||
* @param {string} api API identifier
|
||||
* @param {number} responseLength New response length
|
||||
*/
|
||||
static save(api, responseLength) {
|
||||
if (api === 'openai') {
|
||||
this.#originalResponseLength = oai_settings.openai_max_tokens;
|
||||
oai_settings.openai_max_tokens = responseLength;
|
||||
} else {
|
||||
this.#originalResponseLength = amount_gen;
|
||||
amount_gen = responseLength;
|
||||
}
|
||||
|
||||
this.#lastApi = api;
|
||||
console.log('[TempResponseLength] Saved original response length:', TempResponseLength.#originalResponseLength);
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore the original response length for the specified API.
|
||||
* @param {string|null} api API identifier
|
||||
* @returns {void}
|
||||
*/
|
||||
static restore(api) {
|
||||
if (this.#originalResponseLength === -1) {
|
||||
return;
|
||||
}
|
||||
if (!api && this.#lastApi) {
|
||||
api = this.#lastApi;
|
||||
}
|
||||
if (api === 'openai') {
|
||||
oai_settings.openai_max_tokens = this.#originalResponseLength;
|
||||
} else {
|
||||
amount_gen = this.#originalResponseLength;
|
||||
}
|
||||
|
||||
console.log('[TempResponseLength] Restored original response length:', this.#originalResponseLength);
|
||||
this.#originalResponseLength = -1;
|
||||
this.#lastApi = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets up an event hook to restore the original response length when the event is emitted.
|
||||
* @param {string} api API identifier
|
||||
* @returns {function(): void} Event hook function
|
||||
*/
|
||||
static setupEventHook(api) {
|
||||
const eventHook = () => {
|
||||
if (this.isCustomized()) {
|
||||
this.restore(api);
|
||||
}
|
||||
};
|
||||
|
||||
switch (api) {
|
||||
case 'openai':
|
||||
eventSource.once(event_types.CHAT_COMPLETION_SETTINGS_READY, eventHook);
|
||||
break;
|
||||
default:
|
||||
eventSource.once(event_types.GENERATE_AFTER_DATA, eventHook);
|
||||
break;
|
||||
}
|
||||
|
||||
return eventHook;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the event hook for the specified API.
|
||||
* @param {string} api API identifier
|
||||
* @param {function(): void} eventHook Previously set up event hook
|
||||
*/
|
||||
static removeEventHook(api, eventHook) {
|
||||
switch (api) {
|
||||
case 'openai':
|
||||
eventSource.removeListener(event_types.CHAT_COMPLETION_SETTINGS_READY, eventHook);
|
||||
break;
|
||||
default:
|
||||
eventSource.removeListener(event_types.GENERATE_AFTER_DATA, eventHook);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -6865,12 +6934,23 @@ function selectKoboldGuiPreset() {
|
||||
.trigger('change');
|
||||
}
|
||||
|
||||
export async function saveSettings(type) {
|
||||
export async function saveSettings(loopCounter = 0) {
|
||||
if (!settingsReady) {
|
||||
console.warn('Settings not ready, aborting save');
|
||||
return;
|
||||
}
|
||||
|
||||
const MAX_RETRIES = 3;
|
||||
if (TempResponseLength.isCustomized()) {
|
||||
if (loopCounter < MAX_RETRIES) {
|
||||
console.warn('Response length is currently being overridden, scheduling another save');
|
||||
saveSettingsDebounced(++loopCounter);
|
||||
return;
|
||||
}
|
||||
console.error('Response length is currently being overridden, but the save loop has reached the maximum number of retries');
|
||||
TempResponseLength.restore(null);
|
||||
}
|
||||
|
||||
//console.log('Entering settings with name1 = '+name1);
|
||||
return jQuery.ajax({
|
||||
type: 'POST',
|
||||
|
@ -682,9 +682,9 @@ function getExtensionData(extension) {
|
||||
* @return {string} - The HTML string for the module information.
|
||||
*/
|
||||
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 `
|
||||
<h3>Modules provided by your Extras API:</h3>
|
||||
<h3>` + t`Modules provided by your Extras API:` + `</h3>
|
||||
${moduleInfo}
|
||||
`;
|
||||
}
|
||||
@ -703,11 +703,11 @@ async function showExtensionsDetails() {
|
||||
initialScrollTop = oldPopup.content.scrollTop;
|
||||
await oldPopup.completeCancelled();
|
||||
}
|
||||
const htmlDefault = $('<div class="marginBot10"><h3 class="textAlignCenter">Built-in Extensions:</h3></div>');
|
||||
const htmlExternal = $('<div class="marginBot10"><h3 class="textAlignCenter">Installed 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">' + t`Installed Extensions:` + '</h3></div>');
|
||||
const htmlLoading = $(`<div class="flex-container alignItemsCenter justifyCenter marginTop10 marginBot5">
|
||||
<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>`);
|
||||
|
||||
htmlExternal.append(htmlLoading);
|
||||
@ -728,7 +728,7 @@ async function showExtensionsDetails() {
|
||||
|
||||
/** @type {import('./popup.js').CustomPopupButton} */
|
||||
const updateAllButton = {
|
||||
text: 'Update all',
|
||||
text: t`Update all`,
|
||||
appendAtEnd: true,
|
||||
action: async () => {
|
||||
requiresReload = true;
|
||||
@ -740,7 +740,7 @@ async function showExtensionsDetails() {
|
||||
let waitingForSave = false;
|
||||
|
||||
const popup = new Popup(html, POPUP_TYPE.TEXT, '', {
|
||||
okButton: 'Close',
|
||||
okButton: t`Close`,
|
||||
wide: true,
|
||||
large: true,
|
||||
customButtons: [updateAllButton],
|
||||
@ -833,7 +833,7 @@ async function updateExtension(extensionName, quiet) {
|
||||
toastr.success('Extension is already up to date');
|
||||
}
|
||||
} 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) {
|
||||
console.error('Error:', error);
|
||||
@ -1001,7 +1001,7 @@ export async function installExtension(url, global) {
|
||||
}
|
||||
|
||||
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}`);
|
||||
await loadExtensionSettings({}, false, false);
|
||||
await eventSource.emit(event_types.EXTENSION_SETTINGS_LOADED);
|
||||
@ -1175,7 +1175,7 @@ async function checkForExtensionUpdates(force) {
|
||||
await Promise.allSettled(promises);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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 promises = [];
|
||||
for (const [id, manifest] of Object.entries(manifests)) {
|
||||
|
@ -1,10 +1,10 @@
|
||||
<div>
|
||||
<h3>Included settings:</h3>
|
||||
<h3 data-i18n="Included settings:">Included settings:</h3>
|
||||
<div class="justifyLeft flex-container flexFlowColumn flexNoGap">
|
||||
{{#each settings}}
|
||||
<label class="checkbox_label">
|
||||
<input type="checkbox" value="{{@key}}" name="exclude"{{#if this}} checked{{/if}}>
|
||||
<span>{{@key}}</span>
|
||||
<span data-i18n="{{@key}}">{{@key}}</span>
|
||||
</label>
|
||||
{{/each}}
|
||||
</div>
|
||||
|
@ -12,8 +12,8 @@
|
||||
</div>
|
||||
<div class="marginTop5">
|
||||
<small>
|
||||
<b>Hint:</b>
|
||||
<i>Click on the setting name to omit it from the profile.</i>
|
||||
<b data-i18n="Hint:">Hint:</b>
|
||||
<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>
|
||||
</div>
|
||||
<h3 data-i18n="Enter a name:">
|
||||
|
@ -46,10 +46,12 @@
|
||||
<div class="qr--title" data-i18n="Edit Quick Replies">Edit Quick Replies</div>
|
||||
<div class="qr--actions">
|
||||
<select id="qr--set" class="text_pole"></select>
|
||||
<div class="qr--add menu_button menu_button_icon fa-solid fa-pencil" id="qr--set-rename" title="Rename quick reply set"></div>
|
||||
<div class="qr--add menu_button menu_button_icon fa-solid fa-plus" id="qr--set-new" title="Create new quick reply set"></div>
|
||||
<div class="qr--add menu_button menu_button_icon fa-solid fa-file-import" id="qr--set-import" title="Import quick reply set"></div>
|
||||
<input type="file" id="qr--set-importFile" accept=".json" hidden>
|
||||
<div class="qr--add menu_button menu_button_icon fa-solid fa-file-export" id="qr--set-export" title="Export quick reply set"></div>
|
||||
<div class="qr-add menu_button menu_button_icon fa-solid fa-paste" id="qr--set-duplicate" title="Duplicate quick reply set"></div>
|
||||
<div class="qr--del menu_button menu_button_icon fa-solid fa-trash redWarningBG" id="qr--set-delete" title="Delete quick reply set"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { callPopup } from '../../../../../script.js';
|
||||
import { Popup } from '../../../../popup.js';
|
||||
import { getSortableDelay } from '../../../../utils.js';
|
||||
import { log, warn } from '../../index.js';
|
||||
import { QuickReply } from '../QuickReply.js';
|
||||
@ -111,6 +111,7 @@ export class SettingsUi {
|
||||
|
||||
prepareQrEditor() {
|
||||
// qr editor
|
||||
this.dom.querySelector('#qr--set-rename').addEventListener('click', async () => this.renameQrSet());
|
||||
this.dom.querySelector('#qr--set-new').addEventListener('click', async()=>this.addQrSet());
|
||||
/**@type {HTMLInputElement}*/
|
||||
const importFile = this.dom.querySelector('#qr--set-importFile');
|
||||
@ -119,7 +120,8 @@ export class SettingsUi {
|
||||
importFile.value = null;
|
||||
});
|
||||
this.dom.querySelector('#qr--set-import').addEventListener('click', ()=>importFile.click());
|
||||
this.dom.querySelector('#qr--set-export').addEventListener('click', async()=>this.exportQrSet());
|
||||
this.dom.querySelector('#qr--set-export').addEventListener('click', async () => this.exportQrSet());
|
||||
this.dom.querySelector('#qr--set-duplicate').addEventListener('click', async () => this.duplicateQrSet());
|
||||
this.dom.querySelector('#qr--set-delete').addEventListener('click', async()=>this.deleteQrSet());
|
||||
this.dom.querySelector('#qr--set-add').addEventListener('click', async()=>{
|
||||
this.currentQrSet.addQuickReply();
|
||||
@ -279,7 +281,7 @@ export class SettingsUi {
|
||||
}
|
||||
|
||||
async deleteQrSet() {
|
||||
const confirmed = await callPopup(`Are you sure you want to delete the Quick Reply Set "${this.currentQrSet.name}"?<br>This cannot be undone.`, 'confirm');
|
||||
const confirmed = await Popup.show.confirm('Delete Quick Reply Set', `Are you sure you want to delete the Quick Reply Set "${this.currentQrSet.name}"?<br>This cannot be undone.`);
|
||||
if (confirmed) {
|
||||
await this.doDeleteQrSet(this.currentQrSet);
|
||||
this.rerender();
|
||||
@ -303,12 +305,52 @@ export class SettingsUi {
|
||||
this.settings.save();
|
||||
}
|
||||
|
||||
async renameQrSet() {
|
||||
const newName = await Popup.show.input('Rename Quick Reply Set', 'Enter a new name:', this.currentQrSet.name);
|
||||
if (newName && newName.length > 0) {
|
||||
const existingSet = QuickReplySet.get(newName);
|
||||
if (existingSet) {
|
||||
toastr.error(`A Quick Reply Set named "${newName}" already exists.`);
|
||||
return;
|
||||
}
|
||||
const oldName = this.currentQrSet.name;
|
||||
this.currentQrSet.name = newName;
|
||||
await this.currentQrSet.save();
|
||||
|
||||
// Update it in both set lists
|
||||
this.settings.config.setList.forEach(set => {
|
||||
if (set.set.name === oldName) {
|
||||
set.set.name = newName;
|
||||
}
|
||||
});
|
||||
this.settings.chatConfig?.setList.forEach(set => {
|
||||
if (set.set.name === oldName) {
|
||||
set.set.name = newName;
|
||||
}
|
||||
});
|
||||
this.settings.save();
|
||||
|
||||
// Update the option in the current selected QR dropdown. All others will be refreshed via the prepare calls below.
|
||||
/** @type {HTMLOptionElement} */
|
||||
const option = this.currentSet.querySelector(`#qr--set option[value="${oldName}"]`);
|
||||
option.value = newName;
|
||||
option.textContent = newName;
|
||||
|
||||
this.currentSet.value = newName;
|
||||
this.onQrSetChange();
|
||||
this.prepareGlobalSetList();
|
||||
this.prepareChatSetList();
|
||||
|
||||
console.info(`Quick Reply Set renamed from ""${oldName}" to "${newName}".`);
|
||||
}
|
||||
}
|
||||
|
||||
async addQrSet() {
|
||||
const name = await callPopup('Quick Reply Set Name:', 'input');
|
||||
const name = await Popup.show.input('Create a new World Info', 'Enter a name for the new Quick Reply Set:');
|
||||
if (name && name.length > 0) {
|
||||
const oldQrs = QuickReplySet.get(name);
|
||||
if (oldQrs) {
|
||||
const replace = await callPopup(`A Quick Reply Set named "${name}" already exists.<br>Do you want to overwrite the existing Quick Reply Set?<br>The existing set will be deleted. This cannot be undone.`, 'confirm');
|
||||
const replace = Popup.show.confirm('Replace existing World Info', `A Quick Reply Set named "${name}" already exists.<br>Do you want to overwrite the existing Quick Reply Set?<br>The existing set will be deleted. This cannot be undone.`);
|
||||
if (replace) {
|
||||
const idx = QuickReplySet.list.indexOf(oldQrs);
|
||||
await this.doDeleteQrSet(oldQrs);
|
||||
@ -369,7 +411,7 @@ export class SettingsUi {
|
||||
qrs.init();
|
||||
const oldQrs = QuickReplySet.get(props.name);
|
||||
if (oldQrs) {
|
||||
const replace = await callPopup(`A Quick Reply Set named "${qrs.name}" already exists.<br>Do you want to overwrite the existing Quick Reply Set?<br>The existing set will be deleted. This cannot be undone.`, 'confirm');
|
||||
const replace = Popup.show.confirm('Replace existing World Info', `A Quick Reply Set named "${name}" already exists.<br>Do you want to overwrite the existing Quick Reply Set?<br>The existing set will be deleted. This cannot be undone.`);
|
||||
if (replace) {
|
||||
const idx = QuickReplySet.list.indexOf(oldQrs);
|
||||
await this.doDeleteQrSet(oldQrs);
|
||||
@ -421,6 +463,40 @@ export class SettingsUi {
|
||||
URL.revokeObjectURL(url);
|
||||
}
|
||||
|
||||
async duplicateQrSet() {
|
||||
const newName = await Popup.show.input('Duplicate Quick Reply Set', 'Enter a name for the new Quick Reply Set:', `${this.currentQrSet.name} (Copy)`);
|
||||
if (newName && newName.length > 0) {
|
||||
const existingSet = QuickReplySet.get(newName);
|
||||
if (existingSet) {
|
||||
toastr.error(`A Quick Reply Set named "${newName}" already exists.`);
|
||||
return;
|
||||
}
|
||||
const newQrSet = QuickReplySet.from(JSON.parse(JSON.stringify(this.currentQrSet)));
|
||||
newQrSet.name = newName;
|
||||
newQrSet.qrList = this.currentQrSet.qrList.map(qr => QuickReply.from(JSON.parse(JSON.stringify(qr))));
|
||||
newQrSet.addQuickReply();
|
||||
const idx = QuickReplySet.list.findIndex(it => it.name.toLowerCase().localeCompare(newName.toLowerCase()) == 1);
|
||||
if (idx > -1) {
|
||||
QuickReplySet.list.splice(idx, 0, newQrSet);
|
||||
} else {
|
||||
QuickReplySet.list.push(newQrSet);
|
||||
}
|
||||
const opt = document.createElement('option'); {
|
||||
opt.value = newQrSet.name;
|
||||
opt.textContent = newQrSet.name;
|
||||
if (idx > -1) {
|
||||
this.currentSet.children[idx].insertAdjacentElement('beforebegin', opt);
|
||||
} else {
|
||||
this.currentSet.append(opt);
|
||||
}
|
||||
}
|
||||
this.currentSet.value = newName;
|
||||
this.onQrSetChange();
|
||||
this.prepareGlobalSetList();
|
||||
this.prepareChatSetList();
|
||||
}
|
||||
}
|
||||
|
||||
selectQrSet(qrs) {
|
||||
this.currentSet.value = qrs.name;
|
||||
this.onQrSetChange();
|
||||
|
@ -30,6 +30,8 @@ import { textgen_types, textgenerationwebui_settings } from '../../textgen-setti
|
||||
import { SlashCommandParser } from '../../slash-commands/SlashCommandParser.js';
|
||||
import { SlashCommand } from '../../slash-commands/SlashCommand.js';
|
||||
import { ARGUMENT_TYPE, SlashCommandArgument, SlashCommandNamedArgument } from '../../slash-commands/SlashCommandArgument.js';
|
||||
import { SlashCommandEnumValue, enumTypes } from '../../slash-commands/SlashCommandEnumValue.js';
|
||||
import { slashCommandReturnHelper } from '../../slash-commands/SlashCommandReturnHelper.js';
|
||||
import { callGenericPopup, POPUP_RESULT, POPUP_TYPE } from '../../popup.js';
|
||||
import { generateWebLlmChatPrompt, isWebLlmSupported } from '../shared.js';
|
||||
|
||||
@ -1613,25 +1615,55 @@ jQuery(async () => {
|
||||
callback: async (args, query) => {
|
||||
const clamp = (v) => Number.isNaN(v) ? null : Math.min(1, Math.max(0, v));
|
||||
const threshold = clamp(Number(args?.threshold ?? settings.score_threshold));
|
||||
const validateCount = (v) => Number.isNaN(v) || !Number.isInteger(v) || v < 1 ? null : v;
|
||||
const count = validateCount(Number(args?.count)) ?? settings.chunk_count_db;
|
||||
const source = String(args?.source ?? '');
|
||||
const attachments = source ? getDataBankAttachmentsForSource(source, false) : getDataBankAttachments(false);
|
||||
const collectionIds = await ingestDataBankAttachments(String(source));
|
||||
const queryResults = await queryMultipleCollections(collectionIds, String(query), settings.chunk_count_db, threshold);
|
||||
|
||||
// Map collection IDs to file URLs
|
||||
const queryResults = await queryMultipleCollections(collectionIds, String(query), count, threshold);
|
||||
|
||||
// Get URLs
|
||||
const urls = Object
|
||||
.keys(queryResults)
|
||||
.map(x => attachments.find(y => getFileCollectionId(y.url) === x))
|
||||
.filter(x => x)
|
||||
.map(x => x.url);
|
||||
|
||||
// Gets the actual text content of chunks
|
||||
const getChunksText = () => {
|
||||
let textResult = '';
|
||||
for (const collectionId in queryResults) {
|
||||
const metadata = queryResults[collectionId].metadata?.filter(x => x.text)?.sort((a, b) => a.index - b.index)?.map(x => x.text)?.filter(onlyUnique) || [];
|
||||
textResult += metadata.join('\n') + '\n\n';
|
||||
}
|
||||
return textResult;
|
||||
};
|
||||
|
||||
if (args.return === 'chunks') {
|
||||
return getChunksText();
|
||||
}
|
||||
|
||||
return JSON.stringify(urls);
|
||||
// @ts-ignore
|
||||
return slashCommandReturnHelper.doReturn(args.return ?? 'object', urls, { objectToStringFunc: list => list.join('\n') });
|
||||
|
||||
},
|
||||
aliases: ['databank-search', 'data-bank-search'],
|
||||
helpString: 'Search the Data Bank for a specific query using vector similarity. Returns a list of file URLs with the most relevant content.',
|
||||
namedArgumentList: [
|
||||
new SlashCommandNamedArgument('threshold', 'Threshold for the similarity score in the [0, 1] range. Uses the global config value if not set.', ARGUMENT_TYPE.NUMBER, false, false, ''),
|
||||
new SlashCommandNamedArgument('count', 'Maximum number of query results to return.', ARGUMENT_TYPE.NUMBER, false, false, ''),
|
||||
new SlashCommandNamedArgument('source', 'Optional filter for the attachments by source.', ARGUMENT_TYPE.STRING, false, false, '', ['global', 'character', 'chat']),
|
||||
SlashCommandNamedArgument.fromProps({
|
||||
name: 'return',
|
||||
description: 'How you want the return value to be provided',
|
||||
typeList: [ARGUMENT_TYPE.STRING],
|
||||
defaultValue: 'object',
|
||||
enumList: [
|
||||
new SlashCommandEnumValue('chunks', 'Return the actual content chunks', enumTypes.enum, '{}'),
|
||||
...slashCommandReturnHelper.enumList({ allowObject: true })
|
||||
],
|
||||
forceEnum: true,
|
||||
})
|
||||
],
|
||||
unnamedArgumentList: [
|
||||
new SlashCommandArgument('Query to search by.', ARGUMENT_TYPE.STRING, true, false),
|
||||
|
@ -26,6 +26,12 @@ Handlebars.registerHelper('helperMissing', function () {
|
||||
* @typedef {(nonce: string) => string} MacroFunction
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} CustomMacro
|
||||
* @property {string} key - Macro name (key)
|
||||
* @property {string} description - Optional description of the macro
|
||||
*/
|
||||
|
||||
export class MacrosParser {
|
||||
/**
|
||||
* A map of registered macros.
|
||||
@ -33,12 +39,29 @@ export class MacrosParser {
|
||||
*/
|
||||
static #macros = new Map();
|
||||
|
||||
/**
|
||||
* A map of macro descriptions.
|
||||
* @type {Map<string, string>}
|
||||
*/
|
||||
static #descriptions = new Map();
|
||||
|
||||
/**
|
||||
* Returns an iterator over all registered macros.
|
||||
* @returns {IterableIterator<CustomMacro>}
|
||||
*/
|
||||
static [Symbol.iterator] = function* () {
|
||||
for (const macro of MacrosParser.#macros.keys()) {
|
||||
yield { key: macro, description: MacrosParser.#descriptions.get(macro) };
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* Registers a global macro that can be used anywhere where substitution is allowed.
|
||||
* @param {string} key Macro name (key)
|
||||
* @param {string|MacroFunction} value A string or a function that returns a string
|
||||
* @param {string} [description] Optional description of the macro
|
||||
*/
|
||||
static registerMacro(key, value) {
|
||||
static registerMacro(key, value, description = '') {
|
||||
if (typeof key !== 'string') {
|
||||
throw new Error('Macro key must be a string');
|
||||
}
|
||||
@ -64,6 +87,10 @@ export class MacrosParser {
|
||||
}
|
||||
|
||||
this.#macros.set(key, value);
|
||||
|
||||
if (typeof description === 'string' && description) {
|
||||
this.#descriptions.set(key, description);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@ -88,6 +115,8 @@ export class MacrosParser {
|
||||
if (!deleted) {
|
||||
console.warn(`Macro ${key} was not registered`);
|
||||
}
|
||||
|
||||
this.#descriptions.delete(key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -5491,8 +5491,8 @@ export function initOpenAI() {
|
||||
|
||||
if (!isMobile()) {
|
||||
$('#model_openrouter_select').select2({
|
||||
placeholder: 'Select a model',
|
||||
searchInputPlaceholder: 'Search models...',
|
||||
placeholder: t`Select a model`,
|
||||
searchInputPlaceholder: t`Search models...`,
|
||||
searchInputCssClass: 'text_pole',
|
||||
width: '100%',
|
||||
templateResult: getOpenRouterModelTemplate,
|
||||
|
@ -22,6 +22,8 @@ import { SlashCommandBreakPoint } from './SlashCommandBreakPoint.js';
|
||||
import { SlashCommandDebugController } from './SlashCommandDebugController.js';
|
||||
import { commonEnumProviders } from './SlashCommandCommonEnumsProvider.js';
|
||||
import { SlashCommandBreak } from './SlashCommandBreak.js';
|
||||
import { MacrosParser } from '../macros.js';
|
||||
import { t } from '../i18n.js';
|
||||
|
||||
/** @typedef {import('./SlashCommand.js').NamedArgumentsCapture} NamedArgumentsCapture */
|
||||
/** @typedef {import('./SlashCommand.js').NamedArguments} NamedArguments */
|
||||
@ -494,6 +496,10 @@ export class SlashCommandParser {
|
||||
li.querySelector('tt').textContent,
|
||||
(li.querySelector('tt').remove(),li.innerHTML),
|
||||
));
|
||||
for (const macro of MacrosParser) {
|
||||
if (options.find(it => it.name === macro.key)) continue;
|
||||
options.push(new MacroAutoCompleteOption(macro.key, `{{${macro.key}}}`, macro.description || t`No description provided`));
|
||||
}
|
||||
const result = new AutoCompleteNameResult(
|
||||
macro.name,
|
||||
macro.start + 2,
|
||||
|
@ -5,6 +5,7 @@ import { textgenerationwebui_settings as textgen_settings, textgen_types } from
|
||||
import { tokenizers } from './tokenizers.js';
|
||||
import { renderTemplateAsync } from './templates.js';
|
||||
import { POPUP_TYPE, callGenericPopup } from './popup.js';
|
||||
import { t } from './i18n.js';
|
||||
|
||||
let mancerModels = [];
|
||||
let togetherModels = [];
|
||||
@ -936,71 +937,71 @@ export function initTextGenModels() {
|
||||
|
||||
if (!isMobile()) {
|
||||
$('#mancer_model').select2({
|
||||
placeholder: 'Select a model',
|
||||
searchInputPlaceholder: 'Search models...',
|
||||
placeholder: t`Select a model`,
|
||||
searchInputPlaceholder: t`Search models...`,
|
||||
searchInputCssClass: 'text_pole',
|
||||
width: '100%',
|
||||
templateResult: getMancerModelTemplate,
|
||||
});
|
||||
$('#model_togetherai_select').select2({
|
||||
placeholder: 'Select a model',
|
||||
searchInputPlaceholder: 'Search models...',
|
||||
placeholder: t`Select a model`,
|
||||
searchInputPlaceholder: t`Search models...`,
|
||||
searchInputCssClass: 'text_pole',
|
||||
width: '100%',
|
||||
templateResult: getTogetherModelTemplate,
|
||||
});
|
||||
$('#ollama_model').select2({
|
||||
placeholder: 'Select a model',
|
||||
searchInputPlaceholder: 'Search models...',
|
||||
placeholder: t`Select a model`,
|
||||
searchInputPlaceholder: t`Search models...`,
|
||||
searchInputCssClass: 'text_pole',
|
||||
width: '100%',
|
||||
});
|
||||
$('#tabby_model').select2({
|
||||
placeholder: '[Currently loaded]',
|
||||
searchInputPlaceholder: 'Search models...',
|
||||
placeholder: t`[Currently loaded]`,
|
||||
searchInputPlaceholder: t`Search models...`,
|
||||
searchInputCssClass: 'text_pole',
|
||||
width: '100%',
|
||||
allowClear: true,
|
||||
});
|
||||
$('#model_infermaticai_select').select2({
|
||||
placeholder: 'Select a model',
|
||||
searchInputPlaceholder: 'Search models...',
|
||||
placeholder: t`Select a model`,
|
||||
searchInputPlaceholder: t`Search models...`,
|
||||
searchInputCssClass: 'text_pole',
|
||||
width: '100%',
|
||||
templateResult: getInfermaticAIModelTemplate,
|
||||
});
|
||||
$('#model_dreamgen_select').select2({
|
||||
placeholder: 'Select a model',
|
||||
searchInputPlaceholder: 'Search models...',
|
||||
placeholder: t`Select a model`,
|
||||
searchInputPlaceholder: t`Search models...`,
|
||||
searchInputCssClass: 'text_pole',
|
||||
width: '100%',
|
||||
templateResult: getDreamGenModelTemplate,
|
||||
});
|
||||
$('#openrouter_model').select2({
|
||||
placeholder: 'Select a model',
|
||||
searchInputPlaceholder: 'Search models...',
|
||||
placeholder: t`Select a model`,
|
||||
searchInputPlaceholder: t`Search models...`,
|
||||
searchInputCssClass: 'text_pole',
|
||||
width: '100%',
|
||||
templateResult: getOpenRouterModelTemplate,
|
||||
});
|
||||
$('#vllm_model').select2({
|
||||
placeholder: 'Select a model',
|
||||
searchInputPlaceholder: 'Search models...',
|
||||
placeholder: t`Select a model`,
|
||||
searchInputPlaceholder: t`Search models...`,
|
||||
searchInputCssClass: 'text_pole',
|
||||
width: '100%',
|
||||
templateResult: getVllmModelTemplate,
|
||||
});
|
||||
$('#aphrodite_model').select2({
|
||||
placeholder: 'Select a model',
|
||||
searchInputPlaceholder: 'Search models...',
|
||||
placeholder: t`Select a model`,
|
||||
searchInputPlaceholder: t`Search models...`,
|
||||
searchInputCssClass: 'text_pole',
|
||||
width: '100%',
|
||||
templateResult: getAphroditeModelTemplate,
|
||||
});
|
||||
providersSelect.select2({
|
||||
sorter: data => data.sort((a, b) => a.text.localeCompare(b.text)),
|
||||
placeholder: 'Select providers. No selection = all providers.',
|
||||
searchInputPlaceholder: 'Search providers...',
|
||||
placeholder: t`Select providers. No selection = all providers.`,
|
||||
searchInputPlaceholder: t`Search providers...`,
|
||||
searchInputCssClass: 'text_pole',
|
||||
width: '100%',
|
||||
closeOnSelect: false,
|
||||
|
@ -20,6 +20,7 @@ import { SlashCommandClosure } from './slash-commands/SlashCommandClosure.js';
|
||||
import { callGenericPopup, Popup, POPUP_TYPE } from './popup.js';
|
||||
import { StructuredCloneMap } from './util/StructuredCloneMap.js';
|
||||
import { renderTemplateAsync } from './templates.js';
|
||||
import { t } from './i18n.js';
|
||||
|
||||
export const world_info_insertion_strategy = {
|
||||
evenly: 0,
|
||||
@ -909,21 +910,21 @@ function registerWorldInfoSlashCommands() {
|
||||
|
||||
async function getEntriesFromFile(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 '';
|
||||
}
|
||||
|
||||
const data = await loadWorldInfo(file);
|
||||
|
||||
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 '';
|
||||
}
|
||||
|
||||
const entries = Object.values(data.entries);
|
||||
|
||||
if (!entries || entries.length === 0) {
|
||||
toastr.warning('World Info file has no entries');
|
||||
toastr.warning(t`World Info file has no entries`);
|
||||
return '';
|
||||
}
|
||||
|
||||
@ -951,7 +952,7 @@ function registerWorldInfoSlashCommands() {
|
||||
name = String(name ?? '') || context.characters[context.characterId]?.avatar || null;
|
||||
const character = findChar({ name });
|
||||
if (!character) {
|
||||
toastr.error('Character not found.');
|
||||
toastr.error(t`Character not found.`);
|
||||
return '';
|
||||
}
|
||||
const books = [];
|
||||
@ -977,7 +978,7 @@ function registerWorldInfoSlashCommands() {
|
||||
const chatId = getCurrentChatId();
|
||||
|
||||
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 '';
|
||||
}
|
||||
|
||||
@ -4773,7 +4774,7 @@ export async function importEmbeddedWorldInfo(skipPopup = false) {
|
||||
const bookName = characters[chid]?.data?.character_book?.name || `${characters[chid]?.name}'s Lorebook`;
|
||||
|
||||
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) {
|
||||
return;
|
||||
}
|
||||
@ -4785,7 +4786,7 @@ export async function importEmbeddedWorldInfo(skipPopup = false) {
|
||||
await updateWorldInfoList();
|
||||
$('#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);
|
||||
if (newIndex >= 0) {
|
||||
@ -4813,9 +4814,9 @@ export function onWorldInfoChange(args, text) {
|
||||
if (selected_world_info.includes(name)) {
|
||||
selected_world_info.splice(selected_world_info.indexOf(name), 1);
|
||||
wiElement.prop('selected', false);
|
||||
if (!silent) toastr.success(`Deactivated world: ${name}`);
|
||||
if (!silent) toastr.success(t`Deactivated world: ${name}`);
|
||||
} else {
|
||||
if (!silent) toastr.error(`World was not active: ${name}`);
|
||||
if (!silent) toastr.error(t`World was not active: ${name}`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -4823,11 +4824,11 @@ export function onWorldInfoChange(args, text) {
|
||||
if (selected_world_info.includes(name)) {
|
||||
selected_world_info.splice(selected_world_info.indexOf(name), 1);
|
||||
wiElement.prop('selected', false);
|
||||
if (!silent) toastr.success(`Deactivated world: ${name}`);
|
||||
if (!silent) toastr.success(t`Deactivated world: ${name}`);
|
||||
} else {
|
||||
selected_world_info.push(name);
|
||||
wiElement.prop('selected', true);
|
||||
if (!silent) toastr.success(`Activated world: ${name}`);
|
||||
if (!silent) toastr.success(t`Activated world: ${name}`);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@ -4835,16 +4836,16 @@ export function onWorldInfoChange(args, text) {
|
||||
default: {
|
||||
selected_world_info.push(name);
|
||||
wiElement.prop('selected', true);
|
||||
if (!silent) toastr.success(`Activated world: ${name}`);
|
||||
if (!silent) toastr.success(t`Activated world: ${name}`);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!silent) toastr.error(`No world found named: ${worldName}`);
|
||||
if (!silent) toastr.error(t`No world found named: ${worldName}`);
|
||||
}
|
||||
});
|
||||
$('#world_info').trigger('change');
|
||||
} 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 = [];
|
||||
$('#world_info').val(null).trigger('change');
|
||||
}
|
||||
@ -4860,7 +4861,7 @@ export function onWorldInfoChange(args, text) {
|
||||
} else {
|
||||
const wiElement = getWIElement(existingWorldName);
|
||||
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) {
|
||||
toastr.error(`File is not valid: ${file.name}`);
|
||||
toastr.error(t`File is not valid: ${file.name}`);
|
||||
return;
|
||||
}
|
||||
|
||||
@ -5038,7 +5039,7 @@ jQuery(() => {
|
||||
|
||||
$('#world_create_button').on('click', async () => {
|
||||
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) {
|
||||
await createNewWorldInfo(finalName, { interactive: true });
|
||||
|
@ -5735,3 +5735,15 @@ body:not(.movingUI) .drawer-content.maximized {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/* Constrict the scroll of alternate greetings to only the dynamic form section */
|
||||
.alternate_grettings {
|
||||
display: grid;
|
||||
grid-template-rows: auto auto auto 1fr;
|
||||
max-height: 100%;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.alternate_greetings_list {
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user