mirror of
https://github.com/willmiao/ComfyUI-Lora-Manager.git
synced 2026-03-24 14:42:11 -03:00
Add Chinese (Simplified and Traditional) localization files and implement i18n tests
- Created zh-CN.json and zh-TW.json for Simplified and Traditional Chinese translations respectively. - Added comprehensive test suite in test_i18n.py to validate JSON structure, server-side i18n functionality, and translation completeness across multiple languages.
This commit is contained in:
@@ -2,26 +2,26 @@
|
||||
<div id="duplicatesBanner" class="duplicates-banner" style="display: none;">
|
||||
<div class="banner-content">
|
||||
<i class="fas fa-exclamation-triangle"></i>
|
||||
<span id="duplicatesCount">Found 0 duplicate groups</span>
|
||||
<i class="fas fa-question-circle help-icon" id="duplicatesHelp" aria-label="Help information"></i>
|
||||
<span id="duplicatesCount">{{ t('duplicates.found', count=0) }}</span>
|
||||
<i class="fas fa-question-circle help-icon" id="duplicatesHelp" aria-label="{{ t('common.actions.help') }}"></i>
|
||||
<div class="banner-actions">
|
||||
<div class="setting-contro" id="badgeToggleControl">
|
||||
<span>Show Duplicates Notification:</span>
|
||||
<span>{{ t('duplicates.showNotification') }}:</span>
|
||||
<label class="toggle-switch">
|
||||
<input type="checkbox" id="badgeToggleInput">
|
||||
<span class="toggle-slider"></span>
|
||||
</label>
|
||||
</div>
|
||||
<button class="btn-delete-selected disabled" onclick="modelDuplicatesManager.deleteSelectedDuplicates()">
|
||||
Delete Selected (<span id="duplicatesSelectedCount">0</span>)
|
||||
{{ t('duplicates.deleteSelected') }} (<span id="duplicatesSelectedCount">0</span>)
|
||||
</button>
|
||||
<button class="btn-exit-mode" onclick="modelDuplicatesManager.exitDuplicateMode()">
|
||||
<i class="fas fa-times"></i> Exit Mode
|
||||
<i class="fas fa-times"></i> {{ t('duplicates.exitMode') }}
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="help-tooltip" id="duplicatesHelpTooltip">
|
||||
<p>Identical hashes mean identical model files, even if they have different names or previews.</p>
|
||||
<p>Keep only one version (preferably with better metadata/previews) and safely delete the others.</p>
|
||||
<p>{{ t('duplicates.help.identicalHashes') }}</p>
|
||||
<p>{{ t('duplicates.help.keepOne') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
<!-- Folder Navigation Sidebar -->
|
||||
<div class="folder-sidebar" id="folderSidebar">
|
||||
<div class="sidebar-header" id="sidebarHeader">
|
||||
<h3><i class="fas fa-home"></i> <span id="sidebarTitle">Model Root</span></h3>
|
||||
<h3><i class="fas fa-home"></i> <span id="sidebarTitle">{{ t('sidebar.modelRoot') }}</span></h3>
|
||||
<div class="sidebar-header-actions">
|
||||
<button class="sidebar-action-btn" id="sidebarCollapseAll" title="Collapse All Folders">
|
||||
<button class="sidebar-action-btn" id="sidebarCollapseAll" title="{{ t('sidebar.collapseAll') }}">
|
||||
<i class="fas fa-compress-alt"></i>
|
||||
</button>
|
||||
<button class="sidebar-action-btn" id="sidebarPinToggle" title="Pin/Unpin Sidebar">
|
||||
<button class="sidebar-action-btn" id="sidebarPinToggle" title="{{ t('sidebar.pinToggle') }}">
|
||||
<i class="fas fa-thumbtack"></i>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -2,80 +2,79 @@
|
||||
<div class="initialization-container" id="initializationContainer">
|
||||
<div class="initialization-content">
|
||||
<div class="initialization-header">
|
||||
<h2 id="initTitle">{% block init_title %}Initializing{% endblock %}</h2>
|
||||
<p class="init-subtitle" id="initSubtitle">{% block init_message %}Preparing your workspace...{% endblock %}
|
||||
<h2 id="initTitle">{% block init_title %}{{ t('initialization.title') }}{% endblock %}</h2>
|
||||
<p class="init-subtitle" id="initSubtitle">{% block init_message %}{{ t('initialization.message') }}{% endblock %}
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="loading-content">
|
||||
<div class="loading-spinner"></div>
|
||||
<div class="loading-status" id="progressStatus">Initializing...</div>
|
||||
<div class="loading-status" id="progressStatus">{{ t('initialization.status') }}</div>
|
||||
<!-- Use initialization-specific classes for the progress bar -->
|
||||
<div class="init-progress-container">
|
||||
<div class="init-progress-bar" id="initProgressBar"></div>
|
||||
</div>
|
||||
<div class="progress-details">
|
||||
<span id="progressPercentage">0%</span>
|
||||
<span id="remainingTime">Estimating time...</span>
|
||||
<span id="remainingTime">{{ t('initialization.estimatingTime') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="tips-container">
|
||||
<div class="tips-header">
|
||||
<i class="fas fa-lightbulb"></i>
|
||||
<h3>Tips & Tricks</h3>
|
||||
<h3>{{ t('initialization.tips.title') }}</h3>
|
||||
</div>
|
||||
<div class="tips-content">
|
||||
<div class="tip-carousel" id="tipCarousel">
|
||||
<div class="tip-item active">
|
||||
<div class="tip-image">
|
||||
<img src="/loras_static/images/tips/civitai-api.png" alt="Civitai API Setup"
|
||||
<img src="/loras_static/images/tips/civitai-api.png" alt="{{ t('initialization.tips.civitai.alt') }}"
|
||||
onerror="this.src='/loras_static/images/no-preview.png'">
|
||||
</div>
|
||||
<div class="tip-text">
|
||||
<h4>Civitai Integration</h4>
|
||||
<p>Connect your Civitai account: Visit Profile Avatar → Settings → API Keys → Add API Key,
|
||||
then paste it in Lora Manager settings.</p>
|
||||
<h4>{{ t('initialization.tips.civitai.title') }}</h4>
|
||||
<p>{{ t('initialization.tips.civitai.description') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tip-item">
|
||||
<div class="tip-image">
|
||||
<img src="/loras_static/images/tips/civitai-download.png" alt="Civitai Download"
|
||||
<img src="/loras_static/images/tips/civitai-download.png" alt="{{ t('initialization.tips.download.alt') }}"
|
||||
onerror="this.src='/loras_static/images/no-preview.png'">
|
||||
</div>
|
||||
<div class="tip-text">
|
||||
<h4>Easy Download</h4>
|
||||
<p>Use Civitai URLs to quickly download and install new models.</p>
|
||||
<h4>{{ t('initialization.tips.download.title') }}</h4>
|
||||
<p>{{ t('initialization.tips.download.description') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tip-item">
|
||||
<div class="tip-image">
|
||||
<img src="/loras_static/images/tips/recipes.png" alt="Recipes"
|
||||
<img src="/loras_static/images/tips/recipes.png" alt="{{ t('initialization.tips.recipes.alt') }}"
|
||||
onerror="this.src='/loras_static/images/no-preview.png'">
|
||||
</div>
|
||||
<div class="tip-text">
|
||||
<h4>Save Recipes</h4>
|
||||
<p>Create recipes to save your favorite model combinations for future use.</p>
|
||||
<h4>{{ t('initialization.tips.recipes.title') }}</h4>
|
||||
<p>{{ t('initialization.tips.recipes.description') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tip-item">
|
||||
<div class="tip-image">
|
||||
<img src="/loras_static/images/tips/filter.png" alt="Filter Models"
|
||||
<img src="/loras_static/images/tips/filter.png" alt="{{ t('initialization.tips.filter.alt') }}"
|
||||
onerror="this.src='/loras_static/images/no-preview.png'">
|
||||
</div>
|
||||
<div class="tip-text">
|
||||
<h4>Fast Filtering</h4>
|
||||
<p>Filter models by tags or base model type using the filter button in the header.</p>
|
||||
<h4>{{ t('initialization.tips.filter.title') }}</h4>
|
||||
<p>{{ t('initialization.tips.filter.description') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="tip-item">
|
||||
<div class="tip-image">
|
||||
<img src="/loras_static/images/tips/search.webp" alt="Quick Search"
|
||||
<img src="/loras_static/images/tips/search.webp" alt="{{ t('initialization.tips.search.alt') }}"
|
||||
onerror="this.src='/loras_static/images/no-preview.png'">
|
||||
</div>
|
||||
<div class="tip-text">
|
||||
<h4>Quick Search</h4>
|
||||
<p>Press Ctrl+F (Cmd+F on Mac) to quickly search within your current view.</p>
|
||||
<h4>{{ t('initialization.tips.search.title') }}</h4>
|
||||
<p>{{ t('initialization.tips.search.description') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -3,18 +3,18 @@
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button class="close" id="closeDownloadModal">×</button>
|
||||
<h2 id="downloadModalTitle">Download Model from URL</h2>
|
||||
<h2 id="downloadModalTitle">{{ t('modals.download.title') }}</h2>
|
||||
</div>
|
||||
|
||||
<!-- Step 1: URL Input -->
|
||||
<div class="download-step" id="urlStep">
|
||||
<div class="input-group">
|
||||
<label for="modelUrl" id="modelUrlLabel">Civitai URL:</label>
|
||||
<input type="text" id="modelUrl" placeholder="https://civitai.com/models/..." />
|
||||
<label for="modelUrl" id="modelUrlLabel">{{ t('modals.download.url') }}:</label>
|
||||
<input type="text" id="modelUrl" placeholder="{{ t('modals.download.placeholder') }}" />
|
||||
<div class="error-message" id="urlError"></div>
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="primary-btn" id="nextFromUrl">Next</button>
|
||||
<button class="primary-btn" id="nextFromUrl">{{ t('common.actions.next') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -24,8 +24,8 @@
|
||||
<!-- Versions will be inserted here dynamically -->
|
||||
</div>
|
||||
<div class="modal-actions">
|
||||
<button class="secondary-btn" id="backToUrlBtn">Back</button>
|
||||
<button class="primary-btn" id="nextFromVersion">Next</button>
|
||||
<button class="secondary-btn" id="backToUrlBtn">{{ t('common.actions.back') }}</button>
|
||||
<button class="primary-btn" id="nextFromVersion">{{ t('common.actions.next') }}</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -35,9 +35,9 @@
|
||||
<!-- Path preview with inline toggle -->
|
||||
<div class="path-preview">
|
||||
<div class="path-preview-header">
|
||||
<label>Download Location Preview:</label>
|
||||
<div class="inline-toggle-container" title="When enabled, files are automatically organized using configured path templates">
|
||||
<span class="inline-toggle-label">Use Default Path</span>
|
||||
<label>{{ t('modals.download.locationPreview') }}:</label>
|
||||
<div class="inline-toggle-container" title="{{ t('modals.download.useDefaultPathTooltip') }}">
|
||||
<span class="inline-toggle-label">{{ t('modals.download.useDefaultPath') }}</span>
|
||||
<div class="toggle-switch">
|
||||
<input type="checkbox" id="useDefaultPath">
|
||||
<label for="useDefaultPath" class="toggle-slider"></label>
|
||||
@@ -45,7 +45,7 @@
|
||||
</div>
|
||||
</div>
|
||||
<div class="path-display" id="targetPathDisplay">
|
||||
<span class="path-text">Select a root directory</span>
|
||||
<span class="path-text">{{ t('modals.download.selectRootDirectory') }}</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
Reference in New Issue
Block a user