Implement internationalization (i18n) system for LoRA Manager

- Added i18n support with automatic language detection based on browser settings.
- Implemented translations for English (en) and Simplified Chinese (zh-CN).
- Created utility functions for text replacement in HTML templates and JavaScript.
- Developed a comprehensive translation key structure for various application components.
- Added formatting functions for numbers, dates, and file sizes according to locale.
- Included RTL language support and dynamic updates for DOM elements.
- Created tests to verify the functionality of the i18n system.
This commit is contained in:
Will Miao
2025-08-28 22:22:26 +08:00
parent 4246908f2e
commit f82908221c
18 changed files with 1786 additions and 121 deletions

View File

@@ -6,57 +6,57 @@
<i class="fas fa-external-link-alt"></i> View on Civitai
</div> -->
<div class="context-menu-item" data-action="refresh-metadata">
<i class="fas fa-sync"></i> Refresh Civitai Data
<i class="fas fa-sync"></i> <span data-i18n="loras.contextMenu.refreshMetadata">Refresh Civitai Data</span>
</div>
<div class="context-menu-item" data-action="relink-civitai">
<i class="fas fa-link"></i> Re-link to Civitai
<i class="fas fa-link"></i> <span data-i18n="loras.contextMenu.relinkCivitai">Re-link to Civitai</span>
</div>
<div class="context-menu-item" data-action="copyname">
<i class="fas fa-copy"></i> Copy LoRA Syntax
<i class="fas fa-copy"></i> <span data-i18n="loras.contextMenu.copySyntax">Copy LoRA Syntax</span>
</div>
<div class="context-menu-item" data-action="sendappend">
<i class="fas fa-paper-plane"></i> Send to Workflow (Append)
<i class="fas fa-paper-plane"></i> <span data-i18n="loras.contextMenu.sendToWorkflowAppend">Send to Workflow (Append)</span>
</div>
<div class="context-menu-item" data-action="sendreplace">
<i class="fas fa-exchange-alt"></i> Send to Workflow (Replace)
<i class="fas fa-exchange-alt"></i> <span data-i18n="loras.contextMenu.sendToWorkflowReplace">Send to Workflow (Replace)</span>
</div>
<div class="context-menu-item" data-action="preview">
<i class="fas fa-folder-open"></i> Open Examples Folder
<i class="fas fa-folder-open"></i> <span data-i18n="loras.contextMenu.openExamples">Open Examples Folder</span>
</div>
<div class="context-menu-item" data-action="download-examples">
<i class="fas fa-download"></i> Download Example Images
<i class="fas fa-download"></i> <span data-i18n="loras.contextMenu.downloadExamples">Download Example Images</span>
</div>
<div class="context-menu-item" data-action="replace-preview">
<i class="fas fa-image"></i> Replace Preview
<i class="fas fa-image"></i> <span data-i18n="loras.contextMenu.replacePreview">Replace Preview</span>
</div>
<div class="context-menu-item" data-action="set-nsfw">
<i class="fas fa-exclamation-triangle"></i> Set Content Rating
<i class="fas fa-exclamation-triangle"></i> <span data-i18n="loras.contextMenu.setContentRating">Set Content Rating</span>
</div>
<div class="context-menu-separator"></div>
<div class="context-menu-item" data-action="move">
<i class="fas fa-folder-open"></i> Move to Folder
<i class="fas fa-folder-open"></i> <span data-i18n="loras.contextMenu.moveToFolder">Move to Folder</span>
</div>
<div class="context-menu-item" data-action="exclude">
<i class="fas fa-eye-slash"></i> Exclude Model
<i class="fas fa-eye-slash"></i> <span data-i18n="loras.contextMenu.excludeModel">Exclude Model</span>
</div>
<div class="context-menu-item delete-item" data-action="delete">
<i class="fas fa-trash"></i> Delete Model
<i class="fas fa-trash"></i> <span data-i18n="loras.contextMenu.deleteModel">Delete Model</span>
</div>
</div>
<div id="nsfwLevelSelector" class="nsfw-level-selector">
<div class="nsfw-level-header">
<h3>Set Content Rating</h3>
<h3 data-i18n="modals.contentRating.title">Set Content Rating</h3>
<button class="close-nsfw-selector"><i class="fas fa-times"></i></button>
</div>
<div class="nsfw-level-content">
<div class="current-level">Current: <span id="currentNSFWLevel">Unknown</span></div>
<div class="current-level"><span data-i18n="modals.contentRating.current">Current:</span> <span id="currentNSFWLevel">Unknown</span></div>
<div class="nsfw-level-options">
<button class="nsfw-level-btn" data-level="1">PG</button>
<button class="nsfw-level-btn" data-level="2">PG13</button>
<button class="nsfw-level-btn" data-level="4">R</button>
<button class="nsfw-level-btn" data-level="8">X</button>
<button class="nsfw-level-btn" data-level="16">XXX</button>
<button class="nsfw-level-btn" data-level="1" data-i18n="modals.contentRating.levels.pg">PG</button>
<button class="nsfw-level-btn" data-level="2" data-i18n="modals.contentRating.levels.pg13">PG13</button>
<button class="nsfw-level-btn" data-level="4" data-i18n="modals.contentRating.levels.r">R</button>
<button class="nsfw-level-btn" data-level="8" data-i18n="modals.contentRating.levels.x">X</button>
<button class="nsfw-level-btn" data-level="16" data-i18n="modals.contentRating.levels.xxx">XXX</button>
</div>
</div>
</div>