feat(i18n): 添加简体中文语言选项并扩展国际化支持

添加了简体中文(zh-cn)语言选项到设置页面的语言选择下拉菜单中。

同时新增了大量国际化字符串。

fix(parser): 提高解析器的鲁棒性

现在会遍历所有json对象检测统一格式,即使AI响应中包含多个JSON对象也能正确识别统一格式。
```
This commit is contained in:
dd178
2026-03-22 14:07:11 +08:00
parent 502646bb92
commit 55aa2a1e6a
21 changed files with 1042 additions and 332 deletions
+81 -75
View File
@@ -1,6 +1,6 @@
<div id="rpg-companion-panel" class="rpg-panel">
<!-- Collapse/Expand Toggle Button -->
<button class="rpg-collapse-toggle" id="rpg-collapse-toggle" title="Collapse/Expand Panel">
<button class="rpg-collapse-toggle" id="rpg-collapse-toggle" title="Collapse/Expand Panel" data-i18n-title="global.collapseExpandPanel">
<i class="fa-solid fa-chevron-right"></i>
</button>
@@ -39,7 +39,7 @@
<div class="rpg-strip-attributes-grid"></div>
</div>
<!-- Refresh Button (bottom) -->
<button id="rpg-strip-refresh" class="rpg-strip-refresh-btn" title="Refresh RPG Info">
<button id="rpg-strip-refresh" class="rpg-strip-refresh-btn" title="Refresh RPG Info" data-i18n-title="global.refreshRpgInfo">
<i class="fa-solid fa-sync"></i>
</button>
</div>
@@ -114,7 +114,7 @@
<div class="rpg-features-row" id="rpg-features-row">
<!-- HTML Prompt Toggle -->
<div class="rpg-toggle-container rpg-feature-col" id="rpg-html-toggle-wrapper">
<label class="rpg-toggle-label" title="Immersive HTML">
<label class="rpg-toggle-label" title="Immersive HTML" data-i18n-title="template.mainPanel.immersiveHtml">
<input type="checkbox" id="rpg-toggle-html-prompt">
<i class="fa-solid fa-code"></i>
<span class="rpg-toggle-text" data-i18n-key="template.mainPanel.immersiveHtml">Immersive HTML</span>
@@ -123,7 +123,7 @@
<!-- Dialogue Coloring Toggle -->
<div class="rpg-toggle-container rpg-feature-col" id="rpg-dialogue-coloring-toggle-wrapper">
<label class="rpg-toggle-label" title="Colored Dialogues">
<label class="rpg-toggle-label" title="Colored Dialogues" data-i18n-title="template.mainPanel.coloredDialogues">
<input type="checkbox" id="rpg-toggle-dialogue-coloring">
<i class="fa-solid fa-palette"></i>
<span class="rpg-toggle-text" data-i18n-key="template.mainPanel.coloredDialogues">Colored Dialogues</span>
@@ -132,7 +132,7 @@
<!-- Deception System Toggle -->
<div class="rpg-toggle-container rpg-feature-col" id="rpg-deception-toggle-wrapper">
<label class="rpg-toggle-label" title="Deception System">
<label class="rpg-toggle-label" title="Deception System" data-i18n-title="template.mainPanel.deceptionSystem">
<input type="checkbox" id="rpg-toggle-deception">
<i class="fa-solid fa-masks-theater"></i>
<span class="rpg-toggle-text" data-i18n-key="template.mainPanel.deceptionSystem">Deception System</span>
@@ -141,7 +141,7 @@
<!-- Omniscience Filter Toggle -->
<div class="rpg-toggle-container rpg-feature-col" id="rpg-omniscience-toggle-wrapper">
<label class="rpg-toggle-label" title="Omniscience Filter">
<label class="rpg-toggle-label" title="Omniscience Filter" data-i18n-title="template.mainPanel.omniscienceFilter">
<input type="checkbox" id="rpg-toggle-omniscience">
<i class="fa-solid fa-eye-slash"></i>
<span class="rpg-toggle-text" data-i18n-key="template.mainPanel.omniscienceFilter">Omniscience Filter</span>
@@ -150,7 +150,7 @@
<!-- CYOA Toggle -->
<div class="rpg-toggle-container rpg-feature-col" id="rpg-cyoa-toggle-wrapper">
<label class="rpg-toggle-label" title="CYOA">
<label class="rpg-toggle-label" title="CYOA" data-i18n-title="template.mainPanel.cyoa">
<input type="checkbox" id="rpg-toggle-cyoa">
<i class="fa-solid fa-list-ol"></i>
<span class="rpg-toggle-text" data-i18n-key="template.mainPanel.cyoa">CYOA</span>
@@ -159,7 +159,7 @@
<!-- Spotify Music Toggle -->
<div class="rpg-toggle-container rpg-feature-col" id="rpg-spotify-toggle-wrapper">
<label class="rpg-toggle-label" title="Spotify Music">
<label class="rpg-toggle-label" title="Spotify Music" data-i18n-title="template.mainPanel.spotifyMusic">
<input type="checkbox" id="rpg-toggle-spotify-music">
<i class="fa-brands fa-spotify"></i>
<span class="rpg-toggle-text" data-i18n-key="template.mainPanel.spotifyMusic">Spotify Music</span>
@@ -168,7 +168,7 @@
<!-- Dynamic Weather Toggle -->
<div class="rpg-toggle-container rpg-feature-col" id="rpg-dynamic-weather-toggle-wrapper">
<label class="rpg-toggle-label" title="Dynamic Weather Effects">
<label class="rpg-toggle-label" title="Dynamic Weather Effects" data-i18n-title="template.mainPanel.dynamicWeatherEffects">
<input type="checkbox" id="rpg-toggle-dynamic-weather">
<i class="fa-solid fa-cloud-sun-rain"></i>
<span class="rpg-toggle-text" data-i18n-key="template.mainPanel.dynamicWeatherEffects">Dynamic Weather</span>
@@ -176,7 +176,7 @@
</div>
<!-- Narrator Mode Toggle -->
<div class="rpg-toggle-container rpg-feature-col" id="rpg-narrator-toggle-wrapper">
<label class="rpg-toggle-label" title="Narrator Mode">
<label class="rpg-toggle-label" title="Narrator Mode" data-i18n-title="template.mainPanel.narratorMode">
<input type="checkbox" id="rpg-toggle-narrator">
<i class="fa-solid fa-book-open"></i>
<span class="rpg-toggle-text" data-i18n-key="template.mainPanel.narratorMode">Narrator Mode</span>
@@ -184,7 +184,7 @@
</div>
<!-- Auto-generate Avatars Toggle -->
<div class="rpg-toggle-container rpg-feature-col" id="rpg-auto-avatars-toggle-wrapper">
<label class="rpg-toggle-label" title="Auto-generate Avatars">
<label class="rpg-toggle-label" title="Auto-generate Avatars" data-i18n-title="template.mainPanel.autoAvatars">
<input type="checkbox" id="rpg-toggle-auto-avatars-panel">
<i class="fa-solid fa-user-plus"></i>
<span class="rpg-toggle-text" data-i18n-key="template.mainPanel.autoAvatars">Auto Avatars</span>
@@ -461,17 +461,19 @@
<div id="rpg-weather-suboptions" style="margin-left: 24px; margin-top: 8px;">
<label class="checkbox_label">
<input type="radio" name="rpg-weather-position" id="rpg-toggle-weather-background" />
<span>Show in Background</span>
<span data-i18n-key="template.settingsModal.display.weatherPosition.background">Show in Background</span>
</label>
<small style="display: block; margin-left: 24px; margin-top: -8px; color: #888; font-size: 11px;">
<small style="display: block; margin-left: 24px; margin-top: -8px; color: #888; font-size: 11px;"
data-i18n-key="template.settingsModal.display.weatherPosition.backgroundNote">
Display weather effects behind the chat (standard behavior).
</small>
<label class="checkbox_label">
<input type="radio" name="rpg-weather-position" id="rpg-toggle-weather-foreground" />
<span>Show in Foreground</span>
<span data-i18n-key="template.settingsModal.display.weatherPosition.foreground">Show in Foreground</span>
</label>
<small style="display: block; margin-left: 24px; margin-top: -8px; color: #888; font-size: 11px;">
<small style="display: block; margin-left: 24px; margin-top: -8px; color: #888; font-size: 11px;"
data-i18n-key="template.settingsModal.display.weatherPosition.foregroundNote">
Display weather effects in front of the chat (experimental).
</small>
</div>
@@ -684,7 +686,7 @@
<input type="password" id="rpg-external-api-key" class="rpg-input" placeholder="sk-..."
style="flex: 1;" />
<button id="rpg-toggle-api-key-visibility" class="menu_button" type="button"
title="Show/Hide API Key" style="padding: 4px 8px;">
title="Show/Hide API Key" data-i18n-title="global.showHideApiKey" style="padding: 4px 8px;">
<i class="fa-solid fa-eye"></i>
</button>
</div>
@@ -789,9 +791,10 @@
<!-- Customize Prompts Button -->
<div style="margin-top: 16px; padding-top: 16px; border-top: 1px solid var(--rpg-border);">
<button id="rpg-open-prompts-editor" class="rpg-btn-customize-prompts">
<i class="fa-solid fa-file-lines" aria-hidden="true"></i> <span>Customize Prompts</span>
<i class="fa-solid fa-file-lines" aria-hidden="true"></i> <span data-i18n-key="template.promptsEditor.button">Customize Prompts</span>
</button>
<small style="display: block; margin-top: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-top: 8px; color: #888; font-size: 11px;"
data-i18n-key="template.promptsEditor.buttonNote">
Edit all AI prompts used for generation, plot progression, and combat encounters.
</small>
</div>
@@ -832,9 +835,9 @@
<header class="rpg-dice-popup-header">
<h3 id="rpg-dice-title">
<i class="fa-solid fa-dice-d20" aria-hidden="true"></i>
<span>Roll Dice</span>
<span data-i18n-key="dice.title">Roll Dice</span>
</h3>
<button id="rpg-dice-popup-close" class="rpg-btn-icon" type="button" aria-label="Close dialog">
<button id="rpg-dice-popup-close" class="rpg-btn-icon" type="button" aria-label="Close dialog" data-i18n-aria-label="global.closeDialog">
<i class="fa-solid fa-times" aria-hidden="true"></i>
</button>
</header>
@@ -843,12 +846,12 @@
<div class="rpg-dice-selector-container">
<div class="rpg-dice-selector">
<div class="rpg-dice-input-group">
<label for="rpg-dice-count">Number of Dice:</label>
<label for="rpg-dice-count" data-i18n-key="dice.numberOfDice">Number of Dice:</label>
<input type="number" id="rpg-dice-count" name="dice-count" min="1" max="20" value="1"
class="rpg-input" />
</div>
<div class="rpg-dice-input-group">
<label for="rpg-dice-sides">Dice Type:</label>
<label for="rpg-dice-sides" data-i18n-key="dice.diceType">Dice Type:</label>
<select id="rpg-dice-sides" name="dice-sides" class="rpg-select">
<option value="4">d4</option>
<option value="6">d6</option>
@@ -862,7 +865,7 @@
</div>
<button id="rpg-dice-roll-btn" class="rpg-btn-primary" type="button">
<i class="fa-solid fa-dice" aria-hidden="true"></i>
<span>Roll Dice</span>
<span data-i18n-key="dice.title">Roll Dice</span>
</button>
</div>
@@ -870,17 +873,17 @@
<div class="rpg-dice-rolling">
<i class="fa-solid fa-dice-d20 fa-spin" aria-hidden="true"></i>
</div>
<div class="rpg-dice-rolling-text">Rolling...</div>
<div class="rpg-dice-rolling-text" data-i18n-key="dice.rolling">Rolling...</div>
</div>
<div id="rpg-dice-result" class="rpg-dice-result" hidden aria-live="polite">
<div class="rpg-dice-result-label">Result:</div>
<div class="rpg-dice-result-label" data-i18n-key="dice.result">Result:</div>
<output id="rpg-dice-result-value" class="rpg-dice-result-value"
for="rpg-dice-count rpg-dice-sides">0</output>
<div id="rpg-dice-result-details" class="rpg-dice-result-details" role="status"></div>
<button id="rpg-dice-save-btn" class="rpg-btn-primary rpg-dice-save-btn" type="button">
<i class="fa-solid fa-check" aria-hidden="true"></i>
<span>Save Roll</span>
<span data-i18n-key="dice.saveRoll">Save Roll</span>
</button>
</div>
</div>
@@ -903,24 +906,24 @@
<!-- Preset Management Section -->
<div class="rpg-preset-management">
<div class="rpg-preset-row">
<label for="rpg-preset-select">Preset:</label>
<label for="rpg-preset-select" data-i18n-key="preset.label">Preset:</label>
<select id="rpg-preset-select" class="rpg-select">
<!-- Options populated by JavaScript -->
</select>
<button id="rpg-preset-new" class="rpg-btn-icon" type="button" title="Create New Preset">
<button id="rpg-preset-new" class="rpg-btn-icon" type="button" title="Create New Preset" data-i18n-title="preset.createNewPresetTitle">
<i class="fa-solid fa-plus"></i>
</button>
<button id="rpg-preset-default" class="rpg-btn-icon" type="button" title="Set as Default Preset">
<button id="rpg-preset-default" class="rpg-btn-icon" type="button" title="Set as Default Preset" data-i18n-title="preset.setDefaultPresetTitle">
<i class="fa-solid fa-star"></i>
</button>
<button id="rpg-preset-delete" class="rpg-btn-icon" type="button" title="Delete Current Preset">
<button id="rpg-preset-delete" class="rpg-btn-icon" type="button" title="Delete Current Preset" data-i18n-title="preset.deleteCurrentPresetTitle">
<i class="fa-solid fa-trash"></i>
</button>
</div>
<div class="rpg-preset-association-row">
<label class="checkbox_label">
<input type="checkbox" id="rpg-preset-associate">
<span>Use this preset for: <strong id="rpg-preset-entity-name">Character</strong></span>
<span data-i18n-key="preset.useThisPresetFor">Use this preset for: </span><strong id="rpg-preset-entity-name">Character</strong>
</label>
</div>
</div>
@@ -985,210 +988,213 @@
<header class="rpg-settings-popup-header">
<h3 id="rpg-prompts-editor-title">
<i class="fa-solid fa-file-lines" aria-hidden="true"></i>
<span>Customize Prompts</span>
<span data-i18n-key="template.promptsEditor.title">Customize Prompts</span>
</h3>
<button id="rpg-close-prompts-editor" class="rpg-popup-close" type="button"
aria-label="Close prompts editor">&times;</button>
</header>
<div class="rpg-settings-popup-body">
<small class="notes" style="display: block; margin-bottom: 16px;">
<small class="notes" style="display: block; margin-bottom: 16px;"
data-i18n-key="template.promptsEditor.description">
Customize the AI prompts used throughout the extension. Leave fields empty to use defaults.
</small>
<!-- HTML Prompt -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-html" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-code"></i> HTML Prompt
<i class="fa-solid fa-code"></i> <span data-i18n-key="template.promptsEditor.htmlPrompt.title">HTML Prompt</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;"
data-i18n-key="template.promptsEditor.htmlPrompt.note">
Injected when "Enable Immersive HTML" is enabled. Affects all generation modes.
</small>
<textarea id="rpg-prompt-html" class="rpg-prompt-textarea" rows="4"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="html" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- Dialogue Coloring Prompt -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-dialogue-coloring" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-palette"></i> Dialogue Coloring Prompt
<i class="fa-solid fa-palette"></i> <span data-i18n-key="template.promptsEditor.dialogueColoringPrompt.title">Dialogue Coloring Prompt</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;"
data-i18n-key="template.promptsEditor.dialogueColoringPrompt.note">
Injected when "Enable Dialogue Coloring" is enabled. Affects all generation modes.
</small>
<textarea id="rpg-prompt-dialogue-coloring" class="rpg-prompt-textarea" rows="4"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="dialogue-coloring" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- Deception System Prompt -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-deception" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-masks-theater"></i> Deception System Prompt
<i class="fa-solid fa-masks-theater"></i> <span data-i18n-key="template.promptsEditor.deceptionPrompt.title">Deception System Prompt</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;" data-i18n-key="template.promptsEditor.deceptionPrompt.note">
Injected when "Enable Deception System" is enabled. Instructs AI to mark lies and deceptions with hidden tags.
</small>
<textarea id="rpg-prompt-deception" class="rpg-prompt-textarea" rows="4"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="deception" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- Omniscience Filter Prompt -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-omniscience" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-eye-slash"></i> Omniscience Filter Prompt
<i class="fa-solid fa-eye-slash"></i> <span data-i18n-key="template.promptsEditor.omnisciencePrompt.title">Omniscience Filter Prompt</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;" data-i18n-key="template.promptsEditor.omnisciencePrompt.note">
Injected when "Enable Omniscience Filter" is enabled. Instructs AI to separate information the player character cannot perceive into hidden filter tags.
</small>
<textarea id="rpg-prompt-omniscience" class="rpg-prompt-textarea" rows="6"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="omniscience" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- CYOA Prompt -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-cyoa" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-list-ol"></i> CYOA Prompt
<i class="fa-solid fa-list-ol"></i> <span data-i18n-key="template.promptsEditor.cyoaPrompt.title">CYOA Prompt</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;" data-i18n-key="template.promptsEditor.cyoaPrompt.note">
Injected when "Enable CYOA" is enabled. Instructs AI to end responses with numbered action choices. Uses very high priority (depth 102) to ensure it's the last instruction.
</small>
<textarea id="rpg-prompt-cyoa" class="rpg-prompt-textarea" rows="4"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="cyoa" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- Spotify Music Prompt -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-spotify" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-brands fa-spotify"></i> Spotify Music Prompt
<i class="fa-brands fa-spotify"></i> <span data-i18n-key="template.promptsEditor.spotifyPrompt.title">Spotify Music Prompt</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;" data-i18n-key="template.promptsEditor.spotifyPrompt.note">
Injected when "Enable Spotify Music" is enabled. Asks AI to suggest appropriate music for the scene.
</small>
<textarea id="rpg-prompt-spotify" class="rpg-prompt-textarea" rows="4"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="spotify" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- Narrator Mode Prompt -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-narrator" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-book-open"></i> Narrator Mode Prompt
<i class="fa-solid fa-book-open"></i> <span data-i18n-key="template.promptsEditor.narratorPrompt.title">Narrator Mode Prompt</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;" data-i18n-key="template.promptsEditor.narratorPrompt.note">
Injected when "Narrator Mode" is enabled. Instructs AI to infer characters from context.
</small>
<textarea id="rpg-prompt-narrator" class="rpg-prompt-textarea" rows="3"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="narrator" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- Context Instructions Prompt -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-context-instructions" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-comment-dots"></i> Context Instructions Prompt
<i class="fa-solid fa-comment-dots"></i> <span data-i18n-key="template.promptsEditor.contextPrompt.title">Context Instructions Prompt</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;" data-i18n-key="template.promptsEditor.contextPrompt.note">
Injected in Separate/External mode after the context summary. Tells the AI how to use the context.
</small>
<textarea id="rpg-prompt-context-instructions" class="rpg-prompt-textarea" rows="4"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="contextInstructions" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- Random Plot Progression Prompt -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-plot-random" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-dice"></i> Random Plot Progression Prompt
<i class="fa-solid fa-dice"></i> <span data-i18n-key="template.promptsEditor.randomPlotPrompt.title">Random Plot Progression Prompt</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;" data-i18n-key="template.promptsEditor.randomPlotPrompt.note">
Injected when the "Randomized Plot" button is clicked. Introduces random elements to the story.
</small>
<textarea id="rpg-prompt-plot-random" class="rpg-prompt-textarea" rows="6"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="plotRandom" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- Natural Plot Progression Prompt -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-plot-natural" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-forward"></i> Natural Plot Progression Prompt
<i class="fa-solid fa-forward"></i> <span data-i18n-key="template.promptsEditor.naturalPlotPrompt.title">Natural Plot Progression Prompt</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;" data-i18n-key="template.promptsEditor.naturalPlotPrompt.note">
Injected when the "Natural Plot" button is clicked. Progresses the story naturally.
</small>
<textarea id="rpg-prompt-plot-natural" class="rpg-prompt-textarea" rows="4"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="plotNatural" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- Avatar Generation Instruction -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-avatar" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-user-circle"></i> Avatar Generation Instruction
<i class="fa-solid fa-user-circle"></i> <span data-i18n-key="template.promptsEditor.avatarPrompt.title">Avatar Generation Instruction</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;" data-i18n-key="template.promptsEditor.avatarPrompt.note">
Instructions for LLM when generating avatar image prompts. Used by Auto-generate Missing Avatars feature.
</small>
<textarea id="rpg-prompt-avatar" class="rpg-prompt-textarea" rows="3"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="avatar" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- Tracker Instructions -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-tracker-instructions" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-list-check"></i> Tracker Instructions
<i class="fa-solid fa-list-check"></i> <span data-i18n-key="template.promptsEditor.trackerPrompt.title">Tracker Instructions</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;" data-i18n-key="template.promptsEditor.trackerPrompt.note">
Instruction portion only (format specification is hardcoded). {userName} will be replaced with the user's name.
</small>
<textarea id="rpg-prompt-tracker-instructions" class="rpg-prompt-textarea" rows="4"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="trackerInstructions" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- Tracker Continuation Instruction -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-tracker-continuation" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-arrow-right"></i> Tracker Continuation Instruction
<i class="fa-solid fa-arrow-right"></i> <span data-i18n-key="template.promptsEditor.trackerContinuationPrompt.title">Tracker Continuation Instruction</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;" data-i18n-key="template.promptsEditor.trackerContinuationPrompt.note">
Instructions added after tracker format specifications, telling the AI how to continue the narrative.
</small>
<textarea id="rpg-prompt-tracker-continuation" class="rpg-prompt-textarea" rows="4"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="trackerContinuation" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
<!-- Combat Narrative Style Instruction -->
<div class="rpg-prompt-editor-section">
<label for="rpg-prompt-combat-narrative" style="display: block; margin-bottom: 8px; font-weight: 600;">
<i class="fa-solid fa-fire"></i> Combat Narrative Style Instruction
<i class="fa-solid fa-fire"></i> <span data-i18n-key="template.promptsEditor.combatPrompt.title">Combat Narrative Style Instruction</span>
</label>
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;">
<small style="display: block; margin-bottom: 8px; color: #888; font-size: 11px;" data-i18n-key="template.promptsEditor.combatPrompt.note">
Writing style instructions for combat encounters. Includes prose quality guidelines and anti-repetition rules. {userName} will be replaced with the user's name.
</small>
<textarea id="rpg-prompt-combat-narrative" class="rpg-prompt-textarea" rows="6"></textarea>
<button class="menu_button rpg-restore-prompt-btn" data-prompt="combatNarrative" style="margin-top: 8px;">
<i class="fa-solid fa-rotate-left"></i>&nbsp;Restore Default
<i class="fa-solid fa-rotate-left"></i>&nbsp;<span data-i18n-key="template.promptsEditor.restoreDefault">Restore Default</span>
</button>
</div>
</div>