diff --git a/locales/en.json b/locales/en.json index 85b026b7..0d7789ee 100644 --- a/locales/en.json +++ b/locales/en.json @@ -587,17 +587,6 @@ "recipes": "Loading recipes...", "examples": "Loading examples..." }, - "tags": { - "messages": { - "updated": "Tags updated successfully", - "updateFailed": "Failed to update tags" - }, - "validation": { - "maxLength": "Tag should not exceed 30 characters", - "maxCount": "Maximum 30 tags allowed", - "duplicate": "This tag already exists" - } - }, "recipeTab": { "noRecipesFound": "No recipes found that use this Lora.", "loadingRecipes": "Loading recipes...", @@ -716,11 +705,6 @@ "finalizing": "Finalizing..." } }, - "showcase": { - "exampleImages": { - "deleteFailed": "Failed to delete example image: {error}" - } - }, "duplicates": { "found": "Found {count} duplicate groups", "showNotification": "Show Duplicates Notification", @@ -900,7 +884,11 @@ "renameFailed": "Failed to rename file: {message}", "moveFailed": "Failed to move model(s): {message}", "pleaseSelectRoot": "Please select a {type} root directory", - "nameTooLong": "Model name is limited to 100 characters" + "nameTooLong": "Model name is limited to 100 characters", + "verificationAlreadyDone": "This group has already been verified", + "verificationCompleteMismatch": "Verification complete. {count} file(s) have different actual hashes.", + "verificationCompleteSuccess": "Verification complete. All files are confirmed duplicates.", + "verificationFailed": "Failed to verify hashes: {message}" }, "search": { "atLeastOneOption": "At least one search option must be selected" @@ -930,17 +918,6 @@ "cleared": "Filters cleared" }, "downloads": { - "selectVersion": "Please select a version", - "versionExists": "This version already exists in your library", - "completed": "Download completed successfully", - "alreadyInProgress": "Download already in progress", - "enterLocationFirst": "Please enter a download location first", - "started": "Example images download started", - "startFailed": "Failed to start download", - "paused": "Download paused", - "pauseFailed": "Failed to pause download", - "resumed": "Download resumed", - "resumeFailed": "Failed to resume download", "imagesCompleted": "Example images {action} completed", "imagesFailed": "Example images {action} failed", "loadError": "Error loading downloads: {message}", @@ -966,12 +943,6 @@ "updateFailed": "Failed to update trigger words", "copyFailed": "Copy failed" }, - "examples": { - "pathUpdated": "Example images path updated successfully", - "deleted": "Example image deleted", - "deleteFailed": "Failed to delete example image", - "setPreviewFailed": "Failed to set preview image" - }, "virtual": { "loadFailed": "Failed to load items", "loadMoreFailed": "Failed to load more items", @@ -980,19 +951,28 @@ "bulk": { "unableToSelectAll": "Unable to select all items" }, - "tags": { - "tagTooLong": "Tag is too long (max {max} characters)", - "tooManyTags": "Too many tags (max {max} tags)", - "tagAlreadyExists": "Tag already exists" + "duplicates": { + "findFailed": "Failed to find duplicates: {message}", + "noDuplicatesFound": "No duplicate {type} found", + "noItemsSelected": "No {type} selected for deletion", + "deleteError": "Error: {message}", + "deleteSuccess": "Successfully deleted {count} {type}", + "deleteFailed": "Failed to delete {type}: {message}" }, - "favorites": { - "added": "Added to favorites", - "removed": "Removed from favorites", - "updateFailed": "Failed to update favorite status" + "controls": { + "reloadFailed": "Failed to reload {pageType}: {message}", + "refreshFailed": "Failed to {action} {pageType}: {message}", + "fetchMetadataFailed": "Failed to fetch metadata: {message}", + "clearFilterFailed": "Failed to clear custom filter: {message}" }, - "workflow": { - "checkpointNotImplemented": "Send checkpoint to workflow - feature to be implemented", - "failedToSend": "Failed to send LoRA to workflow" + "contextMenu": { + "contentRatingSet": "Content rating set to {level}", + "contentRatingFailed": "Failed to set content rating: {message}", + "relinkSuccess": "Model successfully re-linked to Civitai", + "relinkFailed": "Error: {message}", + "fetchMetadataFirst": "Please fetch metadata from CivitAI first", + "noCivitaiInfo": "No CivitAI information available", + "missingHash": "Model hash not available" }, "exampleImages": { "checkError": "Error checking for example images", diff --git a/locales/zh-CN.json b/locales/zh-CN.json index 2a6a58a8..56810281 100644 --- a/locales/zh-CN.json +++ b/locales/zh-CN.json @@ -587,17 +587,6 @@ "recipes": "正在加载配方...", "examples": "正在加载示例..." }, - "tags": { - "messages": { - "updated": "标签更新成功", - "updateFailed": "更新标签失败" - }, - "validation": { - "maxLength": "标签长度不能超过30个字符", - "maxCount": "最多允许30个标签", - "duplicate": "该标签已存在" - } - }, "recipeTab": { "noRecipesFound": "未找到使用此 LoRA 的配方。", "loadingRecipes": "正在加载配方...", @@ -897,7 +886,11 @@ "renameFailed": "重命名文件失败:{message}", "moveFailed": "移动模型失败:{message}", "pleaseSelectRoot": "请选择 {type} 根目录", - "nameTooLong": "模型名称限制为100个字符" + "nameTooLong": "模型名称限制为100个字符", + "verificationAlreadyDone": "This group has already been verified", + "verificationCompleteMismatch": "Verification complete. {count} file(s) have different actual hashes.", + "verificationCompleteSuccess": "Verification complete. All files are confirmed duplicates.", + "verificationFailed": "Failed to verify hashes: {message}" }, "search": { "atLeastOneOption": "至少需要选择一个搜索选项" diff --git a/static/js/components/ContextMenu/ModelContextMenuMixin.js b/static/js/components/ContextMenu/ModelContextMenuMixin.js index b8eddbd4..cd376dd1 100644 --- a/static/js/components/ContextMenu/ModelContextMenuMixin.js +++ b/static/js/components/ContextMenu/ModelContextMenuMixin.js @@ -25,10 +25,10 @@ export const ModelContextMenuMixin = { try { await this.saveModelMetadata(filePath, { preview_nsfw_level: level }); - showToast(`Content rating set to ${getNSFWLevelName(level)}`, 'success'); + showToast('toast.contextMenu.contentRatingSet', { level: getNSFWLevelName(level) }, 'success'); this.nsfwSelector.style.display = 'none'; } catch (error) { - showToast(`Failed to set content rating: ${error.message}`, 'error'); + showToast('toast.contextMenu.contentRatingFailed', { message: error.message }, 'error'); } }); }); @@ -147,7 +147,7 @@ export const ModelContextMenuMixin = { const data = await response.json(); if (data.success) { - showToast('Model successfully re-linked to Civitai', 'success'); + showToast('toast.contextMenu.relinkSuccess', {}, 'success'); // Reload the current view to show updated data await this.resetAndReload(); } else { @@ -155,7 +155,7 @@ export const ModelContextMenuMixin = { } } catch (error) { console.error('Error re-linking model:', error); - showToast(`Error: ${error.message}`, 'error'); + showToast('toast.contextMenu.relinkFailed', { message: error.message }, 'error'); } finally { state.loadingManager.hide(); } @@ -211,10 +211,10 @@ export const ModelContextMenuMixin = { if (this.currentCard.querySelector('.fa-globe')) { this.currentCard.querySelector('.fa-globe').click(); } else { - showToast('Please fetch metadata from CivitAI first', 'info'); + showToast('toast.contextMenu.fetchMetadataFirst', {}, 'info'); } } else { - showToast('No CivitAI information available', 'info'); + showToast('toast.contextMenu.noCivitaiInfo', {}, 'info'); } return true; case 'relink-civitai': @@ -232,7 +232,7 @@ export const ModelContextMenuMixin = { async downloadExampleImages() { const modelHash = this.currentCard.dataset.sha256; if (!modelHash) { - showToast('Model hash not available', 'error'); + showToast('toast.contextMenu.missingHash', {}, 'error'); return; } diff --git a/static/js/components/DuplicatesManager.js b/static/js/components/DuplicatesManager.js index 49fb22b2..f49a2d02 100644 --- a/static/js/components/DuplicatesManager.js +++ b/static/js/components/DuplicatesManager.js @@ -26,7 +26,7 @@ export class DuplicatesManager { this.duplicateGroups = data.duplicate_groups || []; if (this.duplicateGroups.length === 0) { - showToast('No duplicate recipes found', 'info'); + showToast('toast.duplicates.noDuplicatesFound', { type: 'recipes' }, 'info'); return false; } @@ -34,7 +34,7 @@ export class DuplicatesManager { return true; } catch (error) { console.error('Error finding duplicates:', error); - showToast('Failed to find duplicates: ' + error.message, 'error'); + showToast('toast.duplicates.findFailed', { message: error.message }, 'error'); return false; } } @@ -325,7 +325,7 @@ export class DuplicatesManager { async deleteSelectedDuplicates() { if (this.selectedForDeletion.size === 0) { - showToast('No recipes selected for deletion', 'info'); + showToast('toast.duplicates.noItemsSelected', { type: 'recipes' }, 'info'); return; } @@ -340,7 +340,7 @@ export class DuplicatesManager { modalManager.showModal('duplicateDeleteModal'); } catch (error) { console.error('Error preparing delete:', error); - showToast('Error: ' + error.message, 'error'); + showToast('toast.duplicates.deleteError', { message: error.message }, 'error'); } } @@ -371,7 +371,7 @@ export class DuplicatesManager { throw new Error(data.error || 'Unknown error deleting recipes'); } - showToast(`Successfully deleted ${data.total_deleted} recipes`, 'success'); + showToast('toast.duplicates.deleteSuccess', { count: data.total_deleted, type: 'recipes' }, 'success'); // Exit duplicate mode if deletions were successful if (data.total_deleted > 0) { @@ -380,7 +380,7 @@ export class DuplicatesManager { } catch (error) { console.error('Error deleting recipes:', error); - showToast('Failed to delete recipes: ' + error.message, 'error'); + showToast('toast.duplicates.deleteFailed', { type: 'recipes', message: error.message }, 'error'); } } } diff --git a/static/js/components/ModelDuplicatesManager.js b/static/js/components/ModelDuplicatesManager.js index 895c72d0..c8879ce9 100644 --- a/static/js/components/ModelDuplicatesManager.js +++ b/static/js/components/ModelDuplicatesManager.js @@ -122,7 +122,7 @@ export class ModelDuplicatesManager { this.updateDuplicatesBadge(this.duplicateGroups.length); if (this.duplicateGroups.length === 0) { - showToast('No duplicate models found', 'info'); + showToast('toast.duplicates.noDuplicatesFound', { type: this.modelType }, 'info'); return false; } @@ -130,7 +130,7 @@ export class ModelDuplicatesManager { return true; } catch (error) { console.error('Error finding duplicates:', error); - showToast('Failed to find duplicates: ' + error.message, 'error'); + showToast('toast.duplicates.findFailed', { message: error.message }, 'error'); return false; } } @@ -594,7 +594,7 @@ export class ModelDuplicatesManager { async deleteSelectedDuplicates() { if (this.selectedForDeletion.size === 0) { - showToast('No models selected for deletion', 'info'); + showToast('toast.duplicates.noItemsSelected', { type: this.modelType }, 'info'); return; } @@ -609,7 +609,7 @@ export class ModelDuplicatesManager { modalManager.showModal('modelDuplicateDeleteModal'); } catch (error) { console.error('Error preparing delete:', error); - showToast('Error: ' + error.message, 'error'); + showToast('toast.duplicates.deleteError', { message: error.message }, 'error'); } } @@ -640,7 +640,7 @@ export class ModelDuplicatesManager { throw new Error(data.error || 'Unknown error deleting models'); } - showToast(`Successfully deleted ${data.total_deleted} models`, 'success'); + showToast('toast.duplicates.deleteSuccess', { count: data.total_deleted, type: this.modelType }, 'success'); // If models were successfully deleted if (data.total_deleted > 0) { @@ -678,7 +678,7 @@ export class ModelDuplicatesManager { } catch (error) { console.error('Error deleting models:', error); - showToast('Failed to delete models: ' + error.message, 'error'); + showToast('toast.duplicates.deleteFailed', { type: this.modelType, message: error.message }, 'error'); } } @@ -745,7 +745,7 @@ export class ModelDuplicatesManager { // Check if already verified if (this.verifiedGroups.has(groupHash)) { - showToast('This group has already been verified', 'info'); + showToast('toast.models.verificationAlreadyDone', {}, 'info'); return; } @@ -793,14 +793,14 @@ export class ModelDuplicatesManager { // Show appropriate toast message if (mismatchedFiles.length > 0) { - showToast(`Verification complete. ${mismatchedFiles.length} file(s) have different actual hashes.`, 'warning'); + showToast('toast.models.verificationCompleteMismatch', { count: mismatchedFiles.length }, 'warning'); } else { - showToast('Verification complete. All files are confirmed duplicates.', 'success'); + showToast('toast.models.verificationCompleteSuccess', {}, 'success'); } } catch (error) { console.error('Error verifying hashes:', error); - showToast('Failed to verify hashes: ' + error.message, 'error'); + showToast('toast.models.verificationFailed', { message: error.message }, 'error'); } finally { // Hide loading state state.loadingManager.hide(); diff --git a/static/js/components/controls/PageControls.js b/static/js/components/controls/PageControls.js index fdd5ad8e..2d6f42f1 100644 --- a/static/js/components/controls/PageControls.js +++ b/static/js/components/controls/PageControls.js @@ -293,7 +293,7 @@ export class PageControls { } } catch (error) { console.error(`Error reloading ${this.pageType}:`, error); - showToast(`Failed to reload ${this.pageType}: ${error.message}`, 'error'); + showToast('toast.controls.reloadFailed', { pageType: this.pageType, message: error.message }, 'error'); } } @@ -316,7 +316,7 @@ export class PageControls { } } catch (error) { console.error(`Error ${fullRebuild ? 'rebuilding' : 'refreshing'} ${this.pageType}:`, error); - showToast(`Failed to ${fullRebuild ? 'rebuild' : 'refresh'} ${this.pageType}: ${error.message}`, 'error'); + showToast('toast.controls.refreshFailed', { action: fullRebuild ? 'rebuild' : 'refresh', pageType: this.pageType, message: error.message }, 'error'); } if (window.modelDuplicatesManager) { @@ -338,7 +338,7 @@ export class PageControls { await this.api.fetchFromCivitai(); } catch (error) { console.error('Error fetching metadata:', error); - showToast('Failed to fetch metadata: ' + error.message, 'error'); + showToast('toast.controls.fetchMetadataFailed', { message: error.message }, 'error'); } } @@ -374,7 +374,7 @@ export class PageControls { await this.api.clearCustomFilter(); } catch (error) { console.error('Error clearing custom filter:', error); - showToast('Failed to clear custom filter: ' + error.message, 'error'); + showToast('toast.controls.clearFilterFailed', { message: error.message }, 'error'); } } diff --git a/static/js/components/shared/RecipeTab.js b/static/js/components/shared/RecipeTab.js index 17e38597..1f34c0d7 100644 --- a/static/js/components/shared/RecipeTab.js +++ b/static/js/components/shared/RecipeTab.js @@ -162,7 +162,7 @@ function getLoraStatusTitle(totalCount, missingCount) { */ function copyRecipeSyntax(recipeId) { if (!recipeId) { - showToast('Cannot copy recipe syntax: Missing recipe ID', 'error'); + showToast('recipeTab.noRecipeId', {}, 'error'); return; } @@ -177,7 +177,7 @@ function copyRecipeSyntax(recipeId) { }) .catch(err => { console.error('Failed to copy: ', err); - showToast('Failed to copy recipe syntax', 'error'); + showToast('recipeTab.copyFailed', {}, 'error'); }); } diff --git a/static/js/components/shared/showcase/MediaUtils.js b/static/js/components/shared/showcase/MediaUtils.js index b7d71632..0da17c53 100644 --- a/static/js/components/shared/showcase/MediaUtils.js +++ b/static/js/components/shared/showcase/MediaUtils.js @@ -445,7 +445,7 @@ export function initMediaControlHandlers(container) { state.virtualScroller.updateSingleItem(result.model_file_path, updateData); } else { // Show error message - showToast('showcase.exampleImages.deleteFailed', { error: result.error }, 'error'); + showToast('toast.exampleImages.deleteFailed', { error: result.error }, 'error'); // Reset button state this.disabled = false; diff --git a/static/js/components/shared/showcase/ShowcaseView.js b/static/js/components/shared/showcase/ShowcaseView.js index 85f9c6f9..ea71d675 100644 --- a/static/js/components/shared/showcase/ShowcaseView.js +++ b/static/js/components/shared/showcase/ShowcaseView.js @@ -430,7 +430,7 @@ async function handleImportFiles(files, modelHash, importContainer) { } } catch (error) { console.error('Error importing examples:', error); - showToast(`Failed to import example images: ${error.message}`, 'error'); + showToast('import.importFailed', { message: error.message }, 'error'); } } diff --git a/static/js/managers/DownloadManager.js b/static/js/managers/DownloadManager.js index 9639f8ec..a3269ea9 100644 --- a/static/js/managers/DownloadManager.js +++ b/static/js/managers/DownloadManager.js @@ -343,7 +343,7 @@ export class DownloadManager { this.updateTargetPath(); } catch (error) { - showToast('downloads.loadError', { message: error.message }, 'error'); + showToast('toast.downloads.loadError', { message: error.message }, 'error'); } } @@ -418,7 +418,7 @@ export class DownloadManager { const config = this.apiClient.apiConfig.config; if (!modelRoot) { - showToast(`Please select a ${config.displayName} root directory`, 'error'); + showToast('models.pleaseSelectRoot', { type: config.displayName }, 'error'); return; } @@ -507,7 +507,7 @@ export class DownloadManager { await resetAndReload(true); } catch (error) { - showToast('downloads.downloadError', { message: error.message }, 'error'); + showToast('toast.downloads.downloadError', { message: error.message }, 'error'); } finally { this.loadingManager.hide(); } diff --git a/static/js/managers/ExampleImagesManager.js b/static/js/managers/ExampleImagesManager.js index 0c5bbe01..a54d65ec 100644 --- a/static/js/managers/ExampleImagesManager.js +++ b/static/js/managers/ExampleImagesManager.js @@ -399,7 +399,7 @@ class ExampleImagesManager { if (data.status.status === 'completed' && !this.hasShownCompletionToast) { const actionType = this.isMigrating ? 'migration' : 'download'; - showToast(`Example images ${actionType} completed`, 'success'); + showToast('toast.downloads.imagesCompleted', { action: actionType }, 'success'); // Mark as shown to prevent duplicate toasts this.hasShownCompletionToast = true; // Reset migration flag @@ -408,7 +408,7 @@ class ExampleImagesManager { setTimeout(() => this.hideProgressPanel(), 5000); } else if (data.status.status === 'error') { const actionType = this.isMigrating ? 'migration' : 'download'; - showToast(`Example images ${actionType} failed`, 'error'); + showToast('toast.downloads.imagesFailed', { action: actionType }, 'error'); this.isMigrating = false; } } diff --git a/static/js/utils/uiHelpers.js b/static/js/utils/uiHelpers.js index c8981e9b..1be00812 100644 --- a/static/js/utils/uiHelpers.js +++ b/static/js/utils/uiHelpers.js @@ -447,7 +447,7 @@ async function sendToSpecificNode(nodeIds, loraSyntax, replaceMode, syntaxType) } else { const messageKey = syntaxType === 'recipe' ? 'uiHelpers.workflow.recipeFailedToSend' : - 'toast.workflow.failedToSend'; + 'uiHelpers.workflow.loraFailedToSend'; showToast(messageKey, {}, 'error'); return false; } @@ -455,7 +455,7 @@ async function sendToSpecificNode(nodeIds, loraSyntax, replaceMode, syntaxType) console.error('Failed to send to workflow:', error); const messageKey = syntaxType === 'recipe' ? 'uiHelpers.workflow.recipeFailedToSend' : - 'toast.workflow.failedToSend'; + 'uiHelpers.workflow.loraFailedToSend'; showToast(messageKey, {}, 'error'); return false; }