Enhance localization and UI for model management features

- Added new localization keys for usage statistics, collection analysis, storage efficiency, and insights in English and Chinese.
- Updated modal templates to utilize localization for delete, exclude, and bulk delete confirmations.
- Improved download modal with localized labels and placeholders.
- Enhanced example access modal with localized titles and descriptions.
- Updated help modal to include localized content for update vlogs and documentation sections.
- Refactored move modal to use localization for labels and buttons.
- Implemented localization in relink Civitai modal for warnings and help text.
- Updated update modal to reflect localized text for actions and progress messages.
- Enhanced statistics template with localized titles for charts and lists.
This commit is contained in:
Will Miao
2025-08-30 23:20:13 +08:00
parent b36fea002e
commit 36d3cd93d5
10 changed files with 360 additions and 110 deletions

View File

@@ -291,7 +291,30 @@
"totalSize": "Total Size",
"favoriteModels": "Favorite Models"
},
"usage": {
"mostUsedLoras": "Most Used LoRAs",
"mostUsedCheckpoints": "Most Used Checkpoints",
"mostUsedEmbeddings": "Most Used Embeddings"
},
"collection": {
"popularTags": "Popular Tags",
"modelTypes": "Model Types",
"collectionAnalysis": "Collection Analysis"
},
"storage": {
"storageUsage": "Storage Usage",
"largestModels": "Largest Models",
"storageEfficiency": "Storage vs Usage Efficiency"
},
"insights": {
"smartInsights": "Smart Insights",
"recommendations": "Recommendations"
},
"charts": {
"collectionOverview": "Collection Overview",
"baseModelDistribution": "Base Model Distribution",
"usageTrends": "Usage Trends (Last 30 Days)",
"usageDistribution": "Usage Distribution",
"modelsByType": "Models by Type",
"modelsByBaseModel": "Models by Base Model",
"modelsBySize": "Models by File Size",
@@ -320,6 +343,12 @@
"useDefaultPath": "Use Default Path",
"useDefaultPathTooltip": "When enabled, files are automatically organized using configured path templates",
"selectRootDirectory": "Select a root directory",
"selectModelRoot": "Select Model Root:",
"targetFolderPath": "Target Folder Path:",
"browseFolders": "Browse Folders:",
"createNewFolder": "Create new folder",
"pathPlaceholder": "Type folder path or select from tree below...",
"root": "Root",
"download": "Download",
"cancel": "Cancel"
},
@@ -341,6 +370,79 @@
"x": "X",
"xxx": "XXX"
}
},
"deleteModel": {
"title": "Delete Model",
"message": "Are you sure you want to delete this model and all associated files?"
},
"excludeModel": {
"title": "Exclude Model",
"message": "Are you sure you want to exclude this model? Excluded models won't appear in searches or model lists."
},
"deleteDuplicateRecipes": {
"title": "Delete Duplicate Recipes",
"message": "Are you sure you want to delete the selected duplicate recipes?",
"countMessage": "recipes will be permanently deleted."
},
"deleteDuplicateModels": {
"title": "Delete Duplicate Models",
"message": "Are you sure you want to delete the selected duplicate models?",
"countMessage": "models will be permanently deleted."
},
"clearCache": {
"title": "Clear Cache Files",
"message": "Are you sure you want to clear all cache files?",
"description": "This will remove all cached model data. The system will need to rebuild the cache on next startup, which may take some time depending on your model collection size.",
"action": "Clear Cache"
},
"bulkDelete": {
"title": "Delete Multiple Models",
"message": "Are you sure you want to delete all selected models and their associated files?",
"countMessage": "models will be permanently deleted.",
"action": "Delete All"
},
"exampleAccess": {
"title": "Local Example Images",
"message": "No local example images found for this model. View options:",
"downloadOption": {
"title": "Download from Civitai",
"description": "Save remote examples locally for offline use and faster loading"
},
"importOption": {
"title": "Import Your Own",
"description": "Add your own custom examples for this model"
},
"footerNote": "Remote examples are still viewable in the model details even without local copies"
},
"moveModel": {
"targetLocationPreview": "Target Location Preview:",
"selectModelRoot": "Select Model Root:",
"targetFolderPath": "Target Folder Path:",
"browseFolders": "Browse Folders:",
"createNewFolder": "Create new folder",
"pathPlaceholder": "Type folder path or select from tree below...",
"root": "Root"
},
"relinkCivitai": {
"title": "Re-link to Civitai",
"warning": "Warning:",
"warningText": "This is a potentially destructive operation. Re-linking will:",
"warningList": {
"overrideMetadata": "Override existing metadata",
"modifyHash": "Potentially modify the model hash",
"unintendedConsequences": "May have other unintended consequences"
},
"proceedText": "Only proceed if you're sure this is what you want.",
"urlLabel": "Civitai Model URL:",
"urlPlaceholder": "https://civitai.com/models/649516/model-name?modelVersionId=726676",
"helpText": {
"title": "Paste any Civitai model URL. Supported formats:",
"format1": "https://civitai.com/models/649516",
"format2": "https://civitai.com/models/649516?modelVersionId=726676",
"format3": "https://civitai.com/models/649516/model-name?modelVersionId=726676",
"note": "Note: If no modelVersionId is provided, the latest version will be used."
},
"confirmAction": "Confirm Re-link"
}
},
"errors": {
@@ -472,13 +574,36 @@
},
"gettingStarted": {
"title": "Getting Started with LoRA Manager"
},
"updateVlogs": {
"title": "Latest Updates",
"watchOnYouTube": "Watch on YouTube",
"playlistTitle": "LoRA Manager Updates Playlist",
"playlistDescription": "Watch all update videos showcasing the latest features and improvements."
},
"documentation": {
"title": "Documentation",
"general": "General",
"troubleshooting": "Troubleshooting",
"modelManagement": "Model Management",
"recipes": "Recipes",
"settings": "Settings & Configuration",
"extensions": "Extensions",
"newBadge": "NEW"
}
},
"update": {
"title": "Check for Updates",
"currentVersion": "Current Version",
"newVersion": "New Version",
"commit": "Commit"
"commit": "Commit",
"viewOnGitHub": "View on GitHub",
"updateNow": "Update Now",
"preparingUpdate": "Preparing update...",
"changelog": "Changelog",
"checkingUpdates": "Checking for updates...",
"checkingMessage": "Please wait while we check for the latest version.",
"showNotifications": "Show update notifications"
},
"support": {
"title": "Support the Project",

View File

@@ -160,10 +160,10 @@
"selectedSuffix": "已选择",
"viewSelected": "点击查看选中项目",
"sendToWorkflow": "发送到工作流",
"copyAll": "复制所有选中的LoRA语法",
"refreshAll": "刷新选中模型的Civitai元数据",
"moveAll": "移动选中模型到文件夹",
"deleteAll": "删除选中模型",
"copyAll": "复制LoRA语法",
"refreshAll": "刷新元数据",
"moveAll": "移动到文件夹",
"deleteAll": "删除",
"clear": "清除选择"
},
"contextMenu": {
@@ -291,7 +291,30 @@
"totalSize": "总大小",
"favoriteModels": "收藏模型"
},
"usage": {
"mostUsedLoras": "最常用的 LoRA",
"mostUsedCheckpoints": "最常用的 Checkpoint",
"mostUsedEmbeddings": "最常用的 Embedding"
},
"collection": {
"popularTags": "热门标签",
"modelTypes": "模型类型",
"collectionAnalysis": "收藏分析"
},
"storage": {
"storageUsage": "存储使用",
"largestModels": "最大的模型",
"storageEfficiency": "存储与使用效率"
},
"insights": {
"smartInsights": "智能洞察",
"recommendations": "建议"
},
"charts": {
"collectionOverview": "收藏概览",
"baseModelDistribution": "基础模型分布",
"usageTrends": "使用趋势最近30天",
"usageDistribution": "使用分布",
"modelsByType": "按类型统计模型",
"modelsByBaseModel": "按基础模型统计",
"modelsBySize": "按文件大小统计",
@@ -320,6 +343,12 @@
"useDefaultPath": "使用默认路径",
"useDefaultPathTooltip": "启用时,文件会使用配置的路径模板自动组织",
"selectRootDirectory": "选择根目录",
"selectModelRoot": "选择模型根目录:",
"targetFolderPath": "目标文件夹路径:",
"browseFolders": "浏览文件夹:",
"createNewFolder": "创建新文件夹",
"pathPlaceholder": "输入文件夹路径或从下面的树中选择...",
"root": "根目录",
"download": "下载",
"cancel": "取消"
},
@@ -341,6 +370,79 @@
"x": "成人级",
"xxx": "重口级"
}
},
"deleteModel": {
"title": "删除模型",
"message": "确定要删除此模型及其所有关联文件吗?"
},
"excludeModel": {
"title": "排除模型",
"message": "确定要排除此模型吗?被排除的模型不会出现在搜索或模型列表中。"
},
"deleteDuplicateRecipes": {
"title": "删除重复配方",
"message": "确定要删除选中的重复配方吗?",
"countMessage": "个配方将被永久删除。"
},
"deleteDuplicateModels": {
"title": "删除重复模型",
"message": "确定要删除选中的重复模型吗?",
"countMessage": "个模型将被永久删除。"
},
"clearCache": {
"title": "清理缓存文件",
"message": "确定要清理所有缓存文件吗?",
"description": "这将删除所有缓存的模型数据。系统需要在下次启动时重建缓存,这可能需要一些时间,具体取决于您的模型收藏规模。",
"action": "清理缓存"
},
"bulkDelete": {
"title": "删除多个模型",
"message": "确定要删除所有选中的模型及其关联文件吗?",
"countMessage": "个模型将被永久删除。",
"action": "全部删除"
},
"exampleAccess": {
"title": "本地示例图片",
"message": "未找到此模型的本地示例图片。查看选项:",
"downloadOption": {
"title": "从 Civitai 下载",
"description": "将远程示例保存到本地,供离线使用和快速加载"
},
"importOption": {
"title": "导入您自己的",
"description": "为此模型添加您自己的自定义示例"
},
"footerNote": "即使没有本地副本,仍可在模型详情中查看远程示例"
},
"moveModel": {
"targetLocationPreview": "目标位置预览:",
"selectModelRoot": "选择模型根目录:",
"targetFolderPath": "目标文件夹路径:",
"browseFolders": "浏览文件夹:",
"createNewFolder": "创建新文件夹",
"pathPlaceholder": "输入文件夹路径或从下面的树中选择...",
"root": "根目录"
},
"relinkCivitai": {
"title": "重新链接到 Civitai",
"warning": "警告:",
"warningText": "这是一个可能具有破坏性的操作。重新链接将:",
"warningList": {
"overrideMetadata": "覆盖现有元数据",
"modifyHash": "可能修改模型哈希值",
"unintendedConsequences": "可能有其他意想不到的后果"
},
"proceedText": "只有在您确定这是您想要的操作时才继续。",
"urlLabel": "Civitai 模型 URL",
"urlPlaceholder": "https://civitai.com/models/649516/model-name?modelVersionId=726676",
"helpText": {
"title": "粘贴任何 Civitai 模型 URL。支持的格式",
"format1": "https://civitai.com/models/649516",
"format2": "https://civitai.com/models/649516?modelVersionId=726676",
"format3": "https://civitai.com/models/649516/model-name?modelVersionId=726676",
"note": "注意:如果未提供 modelVersionId将使用最新版本。"
},
"confirmAction": "确认重新链接"
}
},
"errors": {
@@ -472,13 +574,36 @@
},
"gettingStarted": {
"title": "LoRA 管理器快速入门"
},
"updateVlogs": {
"title": "最新更新",
"watchOnYouTube": "在 YouTube 上观看",
"playlistTitle": "LoRA 管理器更新播放列表",
"playlistDescription": "观看所有展示最新功能和改进的更新视频。"
},
"documentation": {
"title": "文档",
"general": "一般",
"troubleshooting": "故障排除",
"modelManagement": "模型管理",
"recipes": "配方",
"settings": "设置和配置",
"extensions": "扩展",
"newBadge": "新功能"
}
},
"update": {
"title": "检查更新",
"currentVersion": "当前版本",
"newVersion": "新版本",
"commit": "提交"
"commit": "提交",
"viewOnGitHub": "在 GitHub 上查看",
"updateNow": "立即更新",
"preparingUpdate": "准备更新...",
"changelog": "更新日志",
"checkingUpdates": "检查更新中...",
"checkingMessage": "请稍候,我们正在检查最新版本。",
"showNotifications": "显示更新通知"
},
"support": {
"title": "支持项目",

View File

@@ -1,12 +1,12 @@
<!-- Delete Confirmation Modal -->
<div id="deleteModal" class="modal delete-modal">
<div class="modal-content delete-modal-content">
<h2>Delete Model</h2>
<p class="delete-message">Are you sure you want to delete this model and all associated files?</p>
<h2>{{ t('modals.deleteModel.title') }}</h2>
<p class="delete-message">{{ t('modals.deleteModel.message') }}</p>
<div class="delete-model-info"></div>
<div class="modal-actions">
<button class="cancel-btn" onclick="closeDeleteModal()">Cancel</button>
<button class="delete-btn" onclick="confirmDelete()">Delete</button>
<button class="cancel-btn" onclick="closeDeleteModal()">{{ t('common.actions.cancel') }}</button>
<button class="delete-btn" onclick="confirmDelete()">{{ t('common.actions.delete') }}</button>
</div>
</div>
</div>
@@ -14,12 +14,12 @@
<!-- Exclude Confirmation Modal -->
<div id="excludeModal" class="modal delete-modal">
<div class="modal-content delete-modal-content">
<h2>Exclude Model</h2>
<p class="delete-message">Are you sure you want to exclude this model? Excluded models won't appear in searches or model lists.</p>
<h2>{{ t('modals.excludeModel.title') }}</h2>
<p class="delete-message">{{ t('modals.excludeModel.message') }}</p>
<div class="exclude-model-info"></div>
<div class="modal-actions">
<button class="cancel-btn" onclick="closeExcludeModal()">Cancel</button>
<button class="exclude-btn" onclick="confirmExclude()">Exclude</button>
<button class="cancel-btn" onclick="closeExcludeModal()">{{ t('common.actions.cancel') }}</button>
<button class="exclude-btn" onclick="confirmExclude()">{{ t('modals.exclude.confirm') }}</button>
</div>
</div>
</div>
@@ -27,14 +27,14 @@
<!-- Recipes Duplicate Delete Confirmation Modal -->
<div id="duplicateDeleteModal" class="modal delete-modal">
<div class="modal-content delete-modal-content">
<h2>Delete Duplicate Recipes</h2>
<p class="delete-message">Are you sure you want to delete the selected duplicate recipes?</p>
<h2>{{ t('modals.deleteDuplicateRecipes.title') }}</h2>
<p class="delete-message">{{ t('modals.deleteDuplicateRecipes.message') }}</p>
<div class="delete-model-info">
<p><span id="duplicateDeleteCount">0</span> recipes will be permanently deleted.</p>
<p><span id="duplicateDeleteCount">0</span> {{ t('modals.deleteDuplicateRecipes.countMessage') }}</p>
</div>
<div class="modal-actions">
<button class="cancel-btn" onclick="modalManager.closeModal('duplicateDeleteModal')">Cancel</button>
<button class="delete-btn" onclick="recipeManager.confirmDeleteDuplicates()">Delete</button>
<button class="cancel-btn" onclick="modalManager.closeModal('duplicateDeleteModal')">{{ t('common.actions.cancel') }}</button>
<button class="delete-btn" onclick="recipeManager.confirmDeleteDuplicates()">{{ t('common.actions.delete') }}</button>
</div>
</div>
</div>
@@ -42,14 +42,14 @@
<!-- Models Duplicate Delete Confirmation Modal -->
<div id="modelDuplicateDeleteModal" class="modal delete-modal">
<div class="modal-content delete-modal-content">
<h2>Delete Duplicate Models</h2>
<p class="delete-message">Are you sure you want to delete the selected duplicate models?</p>
<h2>{{ t('modals.deleteDuplicateModels.title') }}</h2>
<p class="delete-message">{{ t('modals.deleteDuplicateModels.message') }}</p>
<div class="delete-model-info">
<p><span id="modelDuplicateDeleteCount">0</span> models will be permanently deleted.</p>
<p><span id="modelDuplicateDeleteCount">0</span> {{ t('modals.deleteDuplicateModels.countMessage') }}</p>
</div>
<div class="modal-actions">
<button class="cancel-btn" onclick="modalManager.closeModal('modelDuplicateDeleteModal')">Cancel</button>
<button class="delete-btn" onclick="modelDuplicatesManager.confirmDeleteDuplicates()">Delete</button>
<button class="cancel-btn" onclick="modalManager.closeModal('modelDuplicateDeleteModal')">{{ t('common.actions.cancel') }}</button>
<button class="delete-btn" onclick="modelDuplicatesManager.confirmDeleteDuplicates()">{{ t('common.actions.delete') }}</button>
</div>
</div>
</div>
@@ -57,14 +57,14 @@
<!-- Cache Clear Confirmation Modal -->
<div id="clearCacheModal" class="modal delete-modal">
<div class="modal-content delete-modal-content">
<h2>Clear Cache Files</h2>
<p class="delete-message">Are you sure you want to clear all cache files?</p>
<h2>{{ t('modals.clearCache.title') }}</h2>
<p class="delete-message">{{ t('modals.clearCache.message') }}</p>
<div class="delete-model-info">
<p>This will remove all cached model data. The system will need to rebuild the cache on next startup, which may take some time depending on your model collection size.</p>
<p>{{ t('modals.clearCache.description') }}</p>
</div>
<div class="modal-actions">
<button class="cancel-btn" onclick="modalManager.closeModal('clearCacheModal')">Cancel</button>
<button class="delete-btn" onclick="settingsManager.executeClearCache()">Clear Cache</button>
<button class="cancel-btn" onclick="modalManager.closeModal('clearCacheModal')">{{ t('common.actions.cancel') }}</button>
<button class="delete-btn" onclick="settingsManager.executeClearCache()">{{ t('modals.clearCache.action') }}</button>
</div>
</div>
</div>
@@ -72,14 +72,14 @@
<!-- Bulk Delete Confirmation Modal -->
<div id="bulkDeleteModal" class="modal delete-modal">
<div class="modal-content delete-modal-content">
<h2>Delete Multiple Models</h2>
<p class="delete-message">Are you sure you want to delete all selected models and their associated files?</p>
<h2>{{ t('modals.bulkDelete.title') }}</h2>
<p class="delete-message">{{ t('modals.bulkDelete.message') }}</p>
<div class="delete-model-info">
<p><span id="bulkDeleteCount">0</span> models will be permanently deleted.</p>
<p><span id="bulkDeleteCount">0</span> {{ t('modals.bulkDelete.countMessage') }}</p>
</div>
<div class="modal-actions">
<button class="cancel-btn" onclick="modalManager.closeModal('bulkDeleteModal')">Cancel</button>
<button class="delete-btn" onclick="bulkManager.confirmBulkDelete()">Delete All</button>
<button class="cancel-btn" onclick="modalManager.closeModal('bulkDeleteModal')">{{ t('common.actions.cancel') }}</button>
<button class="delete-btn" onclick="bulkManager.confirmBulkDelete()">{{ t('modals.bulkDelete.action') }}</button>
</div>
</div>
</div>

View File

@@ -51,7 +51,7 @@
<!-- Model Root Selection (always visible) -->
<div class="input-group">
<label for="modelRoot" id="modelRootLabel">Select Model Root:</label>
<label for="modelRoot" id="modelRootLabel">{{ t('modals.download.selectModelRoot') }}</label>
<select id="modelRoot"></select>
</div>
@@ -59,10 +59,10 @@
<div class="manual-path-selection" id="manualPathSelection">
<!-- Path input with autocomplete -->
<div class="input-group">
<label for="folderPath">Target Folder Path:</label>
<label for="folderPath">{{ t('modals.download.targetFolderPath') }}</label>
<div class="path-input-container">
<input type="text" id="folderPath" placeholder="Type folder path or select from tree below..." autocomplete="off" />
<button type="button" id="createFolderBtn" class="create-folder-btn" title="Create new folder">
<input type="text" id="folderPath" placeholder="{{ t('modals.download.pathPlaceholder') }}" autocomplete="off" />
<button type="button" id="createFolderBtn" class="create-folder-btn" title="{{ t('modals.download.createNewFolder') }}">
<i class="fas fa-plus"></i>
</button>
</div>
@@ -72,13 +72,13 @@
<!-- Breadcrumb navigation -->
<div class="breadcrumb-nav" id="breadcrumbNav">
<span class="breadcrumb-item root" data-path="">
<i class="fas fa-home"></i> Root
<i class="fas fa-home"></i> {{ t('modals.download.root') }}
</span>
</div>
<!-- Hierarchical folder tree -->
<div class="input-group">
<label>Browse Folders:</label>
<label>{{ t('modals.download.browseFolders') }}</label>
<div class="folder-tree-container">
<div class="folder-tree" id="folderTree">
<!-- Tree will be loaded dynamically -->
@@ -88,8 +88,8 @@
</div>
</div>
<div class="modal-actions">
<button class="secondary-btn" id="backToVersionsBtn">Back</button>
<button class="primary-btn" id="startDownloadBtn">Download</button>
<button class="secondary-btn" id="backToVersionsBtn">{{ t('common.actions.back') }}</button>
<button class="primary-btn" id="startDownloadBtn">{{ t('modals.download.download') }}</button>
</div>
</div>
</div>

View File

@@ -2,26 +2,26 @@
<div id="exampleAccessModal" class="modal">
<div class="modal-content example-access-modal">
<button class="close" onclick="modalManager.closeModal('exampleAccessModal')">&times;</button>
<h2>Local Example Images</h2>
<p>No local example images found for this model. View options:</p>
<h2>{{ t('modals.exampleAccess.title') }}</h2>
<p>{{ t('modals.exampleAccess.message') }}</p>
<div class="example-access-options">
<button id="downloadExamplesBtn" class="example-option-btn">
<i class="fas fa-cloud-download-alt"></i>
<span class="option-title">Download from Civitai</span>
<span class="option-desc">Save remote examples locally for offline use and faster loading</span>
<span class="option-title">{{ t('modals.exampleAccess.downloadOption.title') }}</span>
<span class="option-desc">{{ t('modals.exampleAccess.downloadOption.description') }}</span>
</button>
<button id="importExamplesBtn" class="example-option-btn">
<i class="fas fa-file-import"></i>
<span class="option-title">Import Your Own</span>
<span class="option-desc">Add your own custom examples for this model</span>
<span class="option-title">{{ t('modals.exampleAccess.importOption.title') }}</span>
<span class="option-desc">{{ t('modals.exampleAccess.importOption.description') }}</span>
</button>
</div>
<div class="modal-footer-note">
<i class="fas fa-info-circle"></i>
<span>Remote examples are still viewable in the model details even without local copies</span>
<span>{{ t('modals.exampleAccess.footerNote') }}</span>
</div>
</div>
</div>

View File

@@ -44,7 +44,7 @@
<!-- Update Vlogs Tab -->
<div class="tab-pane" id="update-vlogs">
<h3>
Latest Updates
{{ t('help.updateVlogs.title') }}
<span class="update-date-badge">
<i class="fas fa-calendar-alt"></i>
Apr 28, 2025
@@ -58,14 +58,14 @@
<div class="video-play-overlay">
<a href="https://www.youtube.com/playlist?list=PLU2fMdHNl8ohz1u7Ke3ooOuMbU5Y4sgoj" target="_blank" class="external-link-btn">
<i class="fas fa-external-link-alt"></i>
<span>Watch on YouTube</span>
<span>{{ t('help.updateVlogs.watchOnYouTube') }}</span>
</a>
</div>
</div>
</div>
<div class="video-info">
<h4>LoRA Manager Updates Playlist</h4>
<p>Watch all update videos showcasing the latest features and improvements.</p>
<h4>{{ t('help.updateVlogs.playlistTitle') }}</h4>
<p>{{ t('help.updateVlogs.playlistDescription') }}</p>
</div>
</div>
</div>
@@ -73,10 +73,10 @@
<!-- Documentation Tab -->
<div class="tab-pane" id="documentation">
<h3>Documentation</h3>
<h3>{{ t('help.documentation.title') }}</h3>
<div class="docs-section">
<h4><i class="fas fa-book"></i> General</h4>
<h4><i class="fas fa-book"></i> {{ t('help.documentation.general') }}</h4>
<ul class="docs-links">
<li><a href="https://github.com/willmiao/ComfyUI-Lora-Manager/wiki" target="_blank">Wiki Home</a></li>
<li><a href="https://github.com/willmiao/ComfyUI-Lora-Manager/blob/main/README.md" target="_blank">README</a></li>
@@ -84,28 +84,28 @@
</div>
<div class="docs-section">
<h4><i class="fas fa-tools"></i> Troubleshooting</h4>
<h4><i class="fas fa-tools"></i> {{ t('help.documentation.troubleshooting') }}</h4>
<ul class="docs-links">
<li><a href="https://github.com/willmiao/ComfyUI-Lora-Manager/wiki/FAQ-(Frequently-Asked-Questions)" target="_blank">FAQ (Frequently Asked Questions)</a></li>
</ul>
</div>
<div class="docs-section">
<h4><i class="fas fa-layer-group"></i> Model Management</h4>
<h4><i class="fas fa-layer-group"></i> {{ t('help.documentation.modelManagement') }}</h4>
<ul class="docs-links">
<li><a href="https://github.com/willmiao/ComfyUI-Lora-Manager/wiki/Example-Images" target="_blank">Example Images (WIP)</a></li>
</ul>
</div>
<div class="docs-section">
<h4><i class="fas fa-book-open"></i> Recipes</h4>
<h4><i class="fas fa-book-open"></i> {{ t('help.documentation.recipes') }}</h4>
<ul class="docs-links">
<li><a href="https://github.com/willmiao/ComfyUI-Lora-Manager/wiki/Recipes-Feature-Tutorial-%E2%80%93-ComfyUI-LoRA-Manager" target="_blank">Recipes Tutorial</a></li>
</ul>
</div>
<div class="docs-section">
<h4><i class="fas fa-cog"></i> Settings & Configuration</h4>
<h4><i class="fas fa-cog"></i> {{ t('help.documentation.settings') }}</h4>
<ul class="docs-links">
<li><a href="https://github.com/willmiao/ComfyUI-Lora-Manager/wiki/Configuration" target="_blank">Configuration Options (WIP)</a></li>
</ul>
@@ -113,14 +113,14 @@
<div class="docs-section">
<h4>
<i class="fas fa-puzzle-piece"></i> Extensions
<span class="new-content-badge">NEW</span>
<i class="fas fa-puzzle-piece"></i> {{ t('help.documentation.extensions') }}
<span class="new-content-badge">{{ t('help.documentation.newBadge') }}</span>
</h4>
<ul class="docs-links">
<li>
<a href="https://github.com/willmiao/ComfyUI-Lora-Manager/wiki/LoRA-Manager-Civitai-Extension-(Chrome-Extension)" target="_blank">
LM Civitai Extension
<span class="new-content-badge inline">NEW</span>
<span class="new-content-badge inline">{{ t('help.documentation.newBadge') }}</span>
</a>
</li>
</ul>

View File

@@ -2,29 +2,29 @@
<div id="moveModal" class="modal">
<div class="modal-content">
<div class="modal-header">
<h2 id="moveModalTitle">Move Model</h2>
<h2 id="moveModalTitle">{{ t('modals.move.title') }}</h2>
<span class="close" onclick="modalManager.closeModal('moveModal')">&times;</span>
</div>
<div class="location-selection">
<!-- Path preview -->
<div class="path-preview">
<label>Target Location Preview:</label>
<label>{{ t('modals.moveModel.targetLocationPreview') }}</label>
<div class="path-display" id="moveTargetPathDisplay">
<span class="path-text">Select a model root directory</span>
<span class="path-text">{{ t('modals.download.selectRootDirectory') }}</span>
</div>
</div>
<div class="input-group">
<label for="moveModelRoot" id="moveRootLabel">Select Model Root:</label>
<label for="moveModelRoot" id="moveRootLabel">{{ t('modals.moveModel.selectModelRoot') }}</label>
<select id="moveModelRoot"></select>
</div>
<!-- Path input with autocomplete -->
<div class="input-group">
<label for="moveFolderPath">Target Folder Path:</label>
<label for="moveFolderPath">{{ t('modals.moveModel.targetFolderPath') }}</label>
<div class="path-input-container">
<input type="text" id="moveFolderPath" placeholder="Type folder path or select from tree below..." autocomplete="off" />
<button type="button" id="moveCreateFolderBtn" class="create-folder-btn" title="Create new folder">
<input type="text" id="moveFolderPath" placeholder="{{ t('modals.moveModel.pathPlaceholder') }}" autocomplete="off" />
<button type="button" id="moveCreateFolderBtn" class="create-folder-btn" title="{{ t('modals.moveModel.createNewFolder') }}">
<i class="fas fa-plus"></i>
</button>
</div>
@@ -34,13 +34,13 @@
<!-- Breadcrumb navigation -->
<div class="breadcrumb-nav" id="moveBreadcrumbNav">
<span class="breadcrumb-item root" data-path="">
<i class="fas fa-home"></i> Root
<i class="fas fa-home"></i> {{ t('modals.moveModel.root') }}
</span>
</div>
<!-- Hierarchical folder tree -->
<div class="input-group">
<label>Browse Folders:</label>
<label>{{ t('modals.moveModel.browseFolders') }}</label>
<div class="folder-tree-container">
<div class="folder-tree" id="moveFolderTree">
<!-- Tree will be loaded dynamically -->
@@ -49,8 +49,8 @@
</div>
</div>
<div class="modal-actions">
<button class="cancel-btn" onclick="modalManager.closeModal('moveModal')">Cancel</button>
<button class="primary-btn" onclick="moveManager.moveModel()">Move</button>
<button class="cancel-btn" onclick="modalManager.closeModal('moveModal')">{{ t('common.actions.cancel') }}</button>
<button class="primary-btn" onclick="moveManager.moveModel()">{{ t('common.actions.move') }}</button>
</div>
</div>
</div>

View File

@@ -2,32 +2,32 @@
<div id="relinkCivitaiModal" class="modal">
<div class="modal-content">
<button class="close" onclick="modalManager.closeModal('relinkCivitaiModal')">&times;</button>
<h2>Re-link to Civitai</h2>
<h2>{{ t('modals.relinkCivitai.title') }}</h2>
<div class="warning-box">
<i class="fas fa-exclamation-triangle"></i>
<p><strong>Warning:</strong> This is a potentially destructive operation. Re-linking will:</p>
<p><strong>{{ t('modals.relinkCivitai.warning') }}</strong> {{ t('modals.relinkCivitai.warningText') }}</p>
<ul>
<li>Override existing metadata</li>
<li>Potentially modify the model hash</li>
<li>May have other unintended consequences</li>
<li>{{ t('modals.relinkCivitai.warningList.overrideMetadata') }}</li>
<li>{{ t('modals.relinkCivitai.warningList.modifyHash') }}</li>
<li>{{ t('modals.relinkCivitai.warningList.unintendedConsequences') }}</li>
</ul>
<p>Only proceed if you're sure this is what you want.</p>
<p>{{ t('modals.relinkCivitai.proceedText') }}</p>
</div>
<div class="input-group">
<label for="civitaiModelUrl">Civitai Model URL:</label>
<input type="text" id="civitaiModelUrl" placeholder="https://civitai.com/models/649516/model-name?modelVersionId=726676" />
<label for="civitaiModelUrl">{{ t('modals.relinkCivitai.urlLabel') }}</label>
<input type="text" id="civitaiModelUrl" placeholder="{{ t('modals.relinkCivitai.urlPlaceholder') }}" />
<div class="input-error" id="civitaiModelUrlError"></div>
<div class="input-help">
Paste any Civitai model URL. Supported formats:<br>
https://civitai.com/models/649516<br>
https://civitai.com/models/649516?modelVersionId=726676<br>
https://civitai.com/models/649516/model-name?modelVersionId=726676<br>
<em>Note: If no modelVersionId is provided, the latest version will be used.</em>
{{ t('modals.relinkCivitai.helpText.title') }}<br>
{{ t('modals.relinkCivitai.helpText.format1') }}<br>
{{ t('modals.relinkCivitai.helpText.format2') }}<br>
{{ t('modals.relinkCivitai.helpText.format3') }}<br>
<em>{{ t('modals.relinkCivitai.helpText.note') }}</em>
</div>
</div>
<div class="modal-actions">
<button class="cancel-btn" onclick="modalManager.closeModal('relinkCivitaiModal')">Cancel</button>
<button class="confirm-btn" id="confirmRelinkBtn">Confirm Re-link</button>
<button class="cancel-btn" onclick="modalManager.closeModal('relinkCivitaiModal')">{{ t('common.actions.cancel') }}</button>
<button class="confirm-btn" id="confirmRelinkBtn">{{ t('modals.relinkCivitai.confirmAction') }}</button>
</div>
</div>
</div>

View File

@@ -22,11 +22,11 @@
<div class="update-actions">
<a href="https://github.com/willmiao/ComfyUI-Lora-Manager" target="_blank" class="update-link">
<i class="fas fa-external-link-alt"></i> View on GitHub
<i class="fas fa-external-link-alt"></i> {{ t('update.viewOnGitHub') }}
</a>
<button id="updateBtn" class="primary-btn disabled">
<i class="fas fa-download"></i>
<span id="updateBtnText">Update Now</span>
<span id="updateBtnText">{{ t('update.updateNow') }}</span>
</button>
</div>
</div>
@@ -34,7 +34,7 @@
<!-- Update Progress Section -->
<div class="update-progress" id="updateProgress" style="display: none;">
<div class="progress-info">
<div class="progress-text" id="updateProgressText">Preparing update...</div>
<div class="progress-text" id="updateProgressText">{{ t('update.preparingUpdate') }}</div>
<div class="update-progress-bar">
<div class="progress-fill" id="updateProgressFill"></div>
</div>
@@ -42,12 +42,12 @@
</div>
<div class="changelog-section">
<h3>Changelog</h3>
<h3>{{ t('update.changelog') }}</h3>
<div class="changelog-content">
<!-- Dynamic changelog content will be inserted here -->
<div class="changelog-item">
<h4>Checking for updates...</h4>
<p>Please wait while we check for the latest version.</p>
<h4>{{ t('update.checkingUpdates') }}</h4>
<p>{{ t('update.checkingMessage') }}</p>
</div>
</div>
</div>
@@ -56,7 +56,7 @@
<label class="toggle-switch">
<input type="checkbox" id="updateNotifications" checked>
<span class="toggle-slider"></span>
<span class="toggle-label">Show update notifications</span>
<span class="toggle-label">{{ t('update.showNotifications') }}</span>
</label>
</div>
</div>

View File

@@ -55,7 +55,7 @@
<div class="panel-grid">
<!-- Collection Overview Chart -->
<div class="chart-container">
<h3><i class="fas fa-pie-chart"></i> Collection Overview</h3>
<h3><i class="fas fa-pie-chart"></i> {{ t('statistics.charts.collectionOverview') }}</h3>
<div class="chart-wrapper">
<canvas id="collectionPieChart"></canvas>
</div>
@@ -63,7 +63,7 @@
<!-- Base Model Distribution -->
<div class="chart-container">
<h3><i class="fas fa-layer-group"></i> Base Model Distribution</h3>
<h3><i class="fas fa-layer-group"></i> {{ t('statistics.charts.baseModelDistribution') }}</h3>
<div class="chart-wrapper">
<canvas id="baseModelChart"></canvas>
</div>
@@ -71,7 +71,7 @@
<!-- Usage Timeline -->
<div class="chart-container full-width">
<h3><i class="fas fa-chart-line"></i> Usage Trends (Last 30 Days)</h3>
<h3><i class="fas fa-chart-line"></i> {{ t('statistics.charts.usageTrends') }}</h3>
<div class="chart-wrapper">
<canvas id="usageTimelineChart"></canvas>
</div>
@@ -84,7 +84,7 @@
<div class="panel-grid">
<!-- Top Used LoRAs -->
<div class="list-container">
<h3><i class="fas fa-star"></i> Most Used LoRAs</h3>
<h3><i class="fas fa-star"></i> {{ t('statistics.usage.mostUsedLoras') }}</h3>
<div class="model-list" id="topLorasList">
<!-- List will be populated by JavaScript -->
</div>
@@ -92,7 +92,7 @@
<!-- Top Used Checkpoints -->
<div class="list-container">
<h3><i class="fas fa-check-circle"></i> Most Used Checkpoints</h3>
<h3><i class="fas fa-check-circle"></i> {{ t('statistics.usage.mostUsedCheckpoints') }}</h3>
<div class="model-list" id="topCheckpointsList">
<!-- List will be populated by JavaScript -->
</div>
@@ -100,7 +100,7 @@
<!-- Top Used Embeddings -->
<div class="list-container">
<h3><i class="fas fa-code"></i> Most Used Embeddings</h3>
<h3><i class="fas fa-code"></i> {{ t('statistics.usage.mostUsedEmbeddings') }}</h3>
<div class="model-list" id="topEmbeddingsList">
<!-- List will be populated by JavaScript -->
</div>
@@ -108,7 +108,7 @@
<!-- Usage Distribution Chart -->
<div class="chart-container full-width">
<h3><i class="fas fa-chart-bar"></i> Usage Distribution</h3>
<h3><i class="fas fa-chart-bar"></i> {{ t('statistics.charts.usageDistribution') }}</h3>
<div class="chart-wrapper">
<canvas id="usageDistributionChart"></canvas>
</div>
@@ -121,7 +121,7 @@
<div class="panel-grid">
<!-- Tag Cloud -->
<div class="chart-container">
<h3><i class="fas fa-tags"></i> Popular Tags</h3>
<h3><i class="fas fa-tags"></i> {{ t('statistics.collection.popularTags') }}</h3>
<div class="tag-cloud" id="tagCloud">
<!-- Tag cloud will be populated by JavaScript -->
</div>
@@ -129,7 +129,7 @@
<!-- Base Model Timeline -->
<div class="chart-container">
<h3><i class="fas fa-history"></i> Model Types</h3>
<h3><i class="fas fa-history"></i> {{ t('statistics.collection.modelTypes') }}</h3>
<div class="chart-wrapper">
<canvas id="modelTypesChart"></canvas>
</div>
@@ -137,7 +137,7 @@
<!-- Collection Growth -->
<div class="chart-container full-width">
<h3><i class="fas fa-chart-area"></i> Collection Analysis</h3>
<h3><i class="fas fa-chart-area"></i> {{ t('statistics.collection.collectionAnalysis') }}</h3>
<div class="analysis-cards" id="collectionAnalysis">
<!-- Analysis cards will be populated by JavaScript -->
</div>
@@ -150,7 +150,7 @@
<div class="panel-grid">
<!-- Storage by Model Type -->
<div class="chart-container">
<h3><i class="fas fa-database"></i> Storage Usage</h3>
<h3><i class="fas fa-database"></i> {{ t('statistics.storage.storageUsage') }}</h3>
<div class="chart-wrapper">
<canvas id="storageChart"></canvas>
</div>
@@ -158,7 +158,7 @@
<!-- Largest Models -->
<div class="list-container">
<h3><i class="fas fa-weight-hanging"></i> Largest Models</h3>
<h3><i class="fas fa-weight-hanging"></i> {{ t('statistics.storage.largestModels') }}</h3>
<div class="model-list" id="largestModelsList">
<!-- List will be populated by JavaScript -->
</div>
@@ -166,7 +166,7 @@
<!-- Storage Efficiency -->
<div class="chart-container full-width">
<h3><i class="fas fa-chart-scatter"></i> Storage vs Usage Efficiency</h3>
<h3><i class="fas fa-chart-scatter"></i> {{ t('statistics.storage.storageEfficiency') }}</h3>
<div class="chart-wrapper">
<canvas id="storageEfficiencyChart"></canvas>
</div>
@@ -177,14 +177,14 @@
<!-- Insights Tab -->
<div class="tab-panel" id="insights-panel">
<div class="insights-container">
<h3><i class="fas fa-lightbulb"></i> Smart Insights</h3>
<h3><i class="fas fa-lightbulb"></i> {{ t('statistics.insights.smartInsights') }}</h3>
<div class="insights-list" id="insightsList">
<!-- Insights will be populated by JavaScript -->
</div>
<!-- Recommendations -->
<div class="recommendations-section">
<h4><i class="fas fa-tasks"></i> Recommendations</h4>
<h4><i class="fas fa-tasks"></i> {{ t('statistics.insights.recommendations') }}</h4>
<div class="recommendations-list" id="recommendationsList">
<!-- Recommendations will be populated by JavaScript -->
</div>