feat(localization): enhance toast messages for API actions and model management with i18n support

refactor(localization): update toast messages in various components and managers for better user feedback
This commit is contained in:
Will Miao
2025-08-31 12:25:08 +08:00
parent be8edafed0
commit e60a579b85
17 changed files with 216 additions and 101 deletions

View File

@@ -830,7 +830,8 @@
"filenameCannotBeEmpty": "File name cannot be empty",
"renameFailed": "Failed to rename file: {message}",
"moveFailed": "Failed to move model(s): {message}",
"pleaseSelectRoot": "Please select a {type} root directory"
"pleaseSelectRoot": "Please select a {type} root directory",
"nameTooLong": "Model name is limited to 100 characters"
},
"search": {
"atLeastOneOption": "At least one search option must be selected"
@@ -887,7 +888,7 @@
"tooLong": "Trigger word should not exceed 30 words",
"tooMany": "Maximum 30 trigger words allowed",
"alreadyExists": "This trigger word already exists",
"updated": "Trigger words updated successfully",
"updateSuccess": "Trigger words updated successfully",
"updateFailed": "Failed to update trigger words",
"copyFailed": "Copy failed"
},
@@ -923,6 +924,34 @@
"checkError": "Error checking for example images",
"missingHash": "Missing model hash information.",
"noRemoteImages": "No remote example images available for this model on Civitai"
},
"api": {
"fetchFailed": "Failed to fetch {type}s: {message}",
"reloadFailed": "Failed to reload {type}s: {message}",
"deleteSuccess": "{type} deleted successfully",
"deleteFailed": "Failed to delete {type}: {message}",
"excludeSuccess": "{type} excluded successfully",
"excludeFailed": "Failed to exclude {type}: {message}",
"fileNameUpdated": "File name updated successfully",
"fileRenameFailed": "Failed to rename file: {error}",
"previewUpdated": "Preview updated successfully",
"previewUploadFailed": "Failed to upload preview image",
"refreshComplete": "{action} complete",
"refreshFailed": "Failed to {action} {type}s",
"metadataUpdateComplete": "Metadata update complete",
"metadataFetchFailed": "Failed to fetch metadata: {message}",
"bulkMetadataFailed": "Failed to refresh metadata: {message}",
"moveNotSupported": "Moving {type}s is not supported",
"alreadyInFolder": "{type} is already in the selected folder",
"moveInfo": "{message}",
"moveSuccess": "{type} moved successfully",
"bulkMoveNotSupported": "Moving {type}s is not supported",
"allAlreadyInFolder": "All selected {type}s are already in the target folder",
"bulkMovePartial": "Moved {successCount} {type}s, {failureCount} failed",
"bulkMoveFailures": "Failed moves:\n{failures}",
"bulkMoveSuccess": "Successfully moved {successCount} {type}s",
"exampleImagesDownloadSuccess": "Successfully downloaded example images!",
"exampleImagesDownloadFailed": "Failed to download example images: {message}"
}
}
}

View File

@@ -786,15 +786,91 @@
"deleteFailed": "错误:{error}",
"deleteFailedGeneral": "删除模型失败",
"selectedAdditional": "额外选择了 {count} 个{type}",
"refreshMetadataFailed": "刷新元数据失败"
"refreshMetadataFailed": "刷新元数据失败",
"nameCannotBeEmpty": "模型名称不能为空",
"nameUpdatedSuccessfully": "模型名称更新成功",
"nameUpdateFailed": "模型名称更新失败",
"baseModelUpdated": "基础模型更新成功",
"baseModelUpdateFailed": "基础模型更新失败",
"invalidCharactersRemoved": "文件名中的无效字符已移除",
"filenameCannotBeEmpty": "文件名不能为空",
"renameFailed": "重命名文件失败:{message}",
"moveFailed": "移动模型失败:{message}",
"pleaseSelectRoot": "请选择 {type} 根目录",
"nameTooLong": "模型名称限制为100个字符"
},
"search": {
"atLeastOneOption": "至少需要选择一个搜索选项"
},
"settings": {
"loraRootsFailed": "加载 LoRA 根目录失败:{message}",
"checkpointRootsFailed": "加载检查点根目录失败:{message}",
"embeddingRootsFailed": "加载嵌入根目录失败:{message}",
"mappingsUpdated": "基础模型路径映射已更新 ({count} 个映射{plural})",
"mappingsCleared": "基础模型路径映射已清除",
"mappingSaveFailed": "保存基础模型映射失败:{message}",
"downloadTemplatesUpdated": "下载路径模板已更新",
"downloadTemplatesFailed": "保存下载路径模板失败:{message}",
"settingsUpdated": "设置已更新:{setting}",
"compactModeToggled": "紧凑模式 {state}",
"compactModeEnabled": "已启用",
"compactModeDisabled": "已禁用",
"settingSaveFailed": "保存设置失败:{message}",
"displayDensitySet": "显示密度设置为 {density}",
"languageChangeFailed": "更改语言失败:{message}",
"cacheCleared": "缓存文件已成功清除。缓存将在下次操作时重建。",
"cacheClearFailed": "清除缓存失败:{error}",
"cacheClearError": "清除缓存错误:{message}"
},
"import": {
"enterRecipeName": "请输入配方名称",
"selectImageFirst": "请先选择图像",
"folderTreeFailed": "加载文件夹树失败",
"folderTreeError": "加载文件夹树错误",
"imagesImported": "示例图片导入成功",
"importFailed": "导入示例图片失败:{message}"
},
"virtual": {
"loadFailed": "加载项目失败",
"loadMoreFailed": "加载更多项目失败",
"loadPositionFailed": "在此位置加载项目失败"
},
"triggerWords": {
"loadFailed": "无法加载训练词汇",
"tooLong": "触发词不应超过30个单词",
"tooMany": "最多允许30个触发词",
"alreadyExists": "此触发词已存在",
"updateSuccess": "触发词更新成功",
"updateFailed": "触发词更新失败",
"copyFailed": "复制失败"
},
"api": {
"fetchFailed": "获取 {type} 失败:{message}",
"reloadFailed": "重新加载 {type} 失败:{message}",
"deleteSuccess": "{type} 删除成功",
"deleteFailed": "删除 {type} 失败:{message}",
"excludeSuccess": "{type} 排除成功",
"excludeFailed": "排除 {type} 失败:{message}",
"fileNameUpdated": "文件名更新成功",
"fileRenameFailed": "重命名文件失败:{error}",
"previewUpdated": "预览图更新成功",
"previewUploadFailed": "上传预览图失败",
"refreshComplete": "{action} 完成",
"refreshFailed": "{action} {type} 失败",
"metadataUpdateComplete": "元数据更新完成",
"metadataFetchFailed": "获取元数据失败:{message}",
"bulkMetadataFailed": "刷新元数据失败:{message}",
"moveNotSupported": "不支持移动 {type}",
"alreadyInFolder": "{type} 已在所选文件夹中",
"moveInfo": "{message}",
"moveSuccess": "{type} 移动成功",
"bulkMoveNotSupported": "不支持移动 {type}",
"allAlreadyInFolder": "所选的所有 {type} 已在目标文件夹中",
"bulkMovePartial": "已移动 {successCount} 个 {type}{failureCount} 个失败",
"bulkMoveFailures": "移动失败:\n{failures}",
"bulkMoveSuccess": "成功移动 {successCount} 个 {type}",
"exampleImagesDownloadSuccess": "示例图片下载成功!",
"exampleImagesDownloadFailed": "示例图片下载失败:{message}"
}
}
}

View File

@@ -76,7 +76,7 @@ export class BaseModelApiClient {
} catch (error) {
console.error(`Error fetching ${this.apiConfig.config.displayName}s:`, error);
showToast(`Failed to fetch ${this.apiConfig.config.displayName}s: ${error.message}`, 'error');
showToast('toast.api.fetchFailed', { type: this.apiConfig.config.displayName, message: error.message }, 'error');
throw error;
}
}
@@ -110,7 +110,7 @@ export class BaseModelApiClient {
return result;
} catch (error) {
console.error(`Error reloading ${this.apiConfig.config.displayName}s:`, error);
showToast(`Failed to reload ${this.apiConfig.config.displayName}s: ${error.message}`, 'error');
showToast('toast.api.reloadFailed', { type: this.apiConfig.config.displayName, message: error.message }, 'error');
throw error;
} finally {
pageState.isLoading = false;
@@ -138,14 +138,14 @@ export class BaseModelApiClient {
if (state.virtualScroller) {
state.virtualScroller.removeItemByFilePath(filePath);
}
showToast(`${this.apiConfig.config.displayName} deleted successfully`, 'success');
showToast('toast.api.deleteSuccess', { type: this.apiConfig.config.displayName }, 'success');
return true;
} else {
throw new Error(data.error || `Failed to delete ${this.apiConfig.config.singularName}`);
}
} catch (error) {
console.error(`Error deleting ${this.apiConfig.config.singularName}:`, error);
showToast(`Failed to delete ${this.apiConfig.config.singularName}: ${error.message}`, 'error');
showToast('toast.api.deleteFailed', { type: this.apiConfig.config.singularName, message: error.message }, 'error');
return false;
} finally {
state.loadingManager.hide();
@@ -172,14 +172,14 @@ export class BaseModelApiClient {
if (state.virtualScroller) {
state.virtualScroller.removeItemByFilePath(filePath);
}
showToast(`${this.apiConfig.config.displayName} excluded successfully`, 'success');
showToast('toast.api.excludeSuccess', { type: this.apiConfig.config.displayName }, 'success');
return true;
} else {
throw new Error(data.error || `Failed to exclude ${this.apiConfig.config.singularName}`);
}
} catch (error) {
console.error(`Error excluding ${this.apiConfig.config.singularName}:`, error);
showToast(`Failed to exclude ${this.apiConfig.config.singularName}: ${error.message}`, 'error');
showToast('toast.api.excludeFailed', { type: this.apiConfig.config.singularName, message: error.message }, 'error');
return false;
} finally {
state.loadingManager.hide();
@@ -208,9 +208,9 @@ export class BaseModelApiClient {
preview_url: result.new_preview_path
});
showToast('File name updated successfully', 'success');
showToast('toast.api.fileNameUpdated', {}, 'success');
} else {
showToast('Failed to rename file: ' + (result.error || 'Unknown error'), 'error');
showToast('toast.api.fileRenameFailed', { error: result.error || 'Unknown error' }, 'error');
}
return result;
@@ -272,10 +272,10 @@ export class BaseModelApiClient {
};
state.virtualScroller.updateSingleItem(filePath, updateData);
showToast('Preview updated successfully', 'success');
showToast('toast.api.previewUpdated', {}, 'success');
} catch (error) {
console.error('Error uploading preview:', error);
showToast('Failed to upload preview image', 'error');
showToast('toast.api.previewUploadFailed', {}, 'error');
} finally {
state.loadingManager.hide();
}
@@ -322,10 +322,10 @@ export class BaseModelApiClient {
resetAndReload(true);
showToast(`${fullRebuild ? 'Full rebuild' : 'Refresh'} complete`, 'success');
showToast('toast.api.refreshComplete', { action: fullRebuild ? 'Full rebuild' : 'Refresh' }, 'success');
} catch (error) {
console.error('Refresh failed:', error);
showToast(`Failed to ${fullRebuild ? 'rebuild' : 'refresh'} ${this.apiConfig.config.displayName}s`, 'error');
showToast('toast.api.refreshFailed', { action: fullRebuild ? 'rebuild' : 'refresh', type: this.apiConfig.config.displayName }, 'error');
} finally {
state.loadingManager.hide();
state.loadingManager.restoreProgressBar();
@@ -353,14 +353,14 @@ export class BaseModelApiClient {
state.virtualScroller.updateSingleItem(filePath, data.metadata);
}
showToast('Metadata refreshed successfully', 'success');
showToast('toast.api.metadataRefreshed', {}, 'success');
return true;
} else {
throw new Error(data.error || 'Failed to refresh metadata');
}
} catch (error) {
console.error('Error refreshing metadata:', error);
showToast(error.message, 'error');
showToast('toast.api.metadataRefreshFailed', { message: error.message }, 'error');
return false;
} finally {
state.loadingManager.hide();
@@ -432,10 +432,10 @@ export class BaseModelApiClient {
await operationComplete;
resetAndReload(false);
showToast('Metadata update complete', 'success');
showToast('toast.api.metadataUpdateComplete', {}, 'success');
} catch (error) {
console.error('Error fetching metadata:', error);
showToast('Failed to fetch metadata: ' + error.message, 'error');
showToast('toast.api.metadataFetchFailed', { message: error.message }, 'error');
} finally {
if (ws) {
ws.close();
@@ -534,7 +534,7 @@ export class BaseModelApiClient {
} catch (error) {
console.error('Error in bulk metadata refresh:', error);
showToast(`Failed to refresh metadata: ${error.message}`, 'error');
showToast('toast.api.bulkMetadataFailed', { message: error.message }, 'error');
await progressController.complete('Operation failed');
throw error;
}
@@ -708,11 +708,11 @@ export class BaseModelApiClient {
async moveSingleModel(filePath, targetPath) {
// Only allow move if supported
if (!this.apiConfig.config.supportsMove) {
showToast(`Moving ${this.apiConfig.config.displayName}s is not supported`, 'warning');
showToast('toast.api.moveNotSupported', { type: this.apiConfig.config.displayName }, 'warning');
return null;
}
if (filePath.substring(0, filePath.lastIndexOf('/')) === targetPath) {
showToast(`${this.apiConfig.config.displayName} is already in the selected folder`, 'info');
showToast('toast.api.alreadyInFolder', { type: this.apiConfig.config.displayName }, 'info');
return null;
}
@@ -737,9 +737,9 @@ export class BaseModelApiClient {
}
if (result && result.message) {
showToast(result.message, 'info');
showToast('toast.api.moveInfo', { message: result.message }, 'info');
} else {
showToast(`${this.apiConfig.config.displayName} moved successfully`, 'success');
showToast('toast.api.moveSuccess', { type: this.apiConfig.config.displayName }, 'success');
}
if (result.success) {
@@ -753,7 +753,7 @@ export class BaseModelApiClient {
async moveBulkModels(filePaths, targetPath) {
if (!this.apiConfig.config.supportsMove) {
showToast(`Moving ${this.apiConfig.config.displayName}s is not supported`, 'warning');
showToast('toast.api.bulkMoveNotSupported', { type: this.apiConfig.config.displayName }, 'warning');
return [];
}
const movedPaths = filePaths.filter(path => {
@@ -761,7 +761,7 @@ export class BaseModelApiClient {
});
if (movedPaths.length === 0) {
showToast(`All selected ${this.apiConfig.config.displayName}s are already in the target folder`, 'info');
showToast('toast.api.allAlreadyInFolder', { type: this.apiConfig.config.displayName }, 'info');
return [];
}
@@ -784,7 +784,11 @@ export class BaseModelApiClient {
if (result.success) {
if (result.failure_count > 0) {
showToast(`Moved ${result.success_count} ${this.apiConfig.config.displayName}s, ${result.failure_count} failed`, 'warning');
showToast('toast.api.bulkMovePartial', {
successCount: result.success_count,
type: this.apiConfig.config.displayName,
failureCount: result.failure_count
}, 'warning');
console.log('Move operation results:', result.results);
const failedFiles = result.results
.filter(r => !r.success)
@@ -796,10 +800,13 @@ export class BaseModelApiClient {
const failureMessage = failedFiles.length <= 3
? failedFiles.join('\n')
: failedFiles.slice(0, 3).join('\n') + `\n(and ${failedFiles.length - 3} more)`;
showToast(`Failed moves:\n${failureMessage}`, 'warning', 6000);
showToast('toast.api.bulkMoveFailures', { failures: failureMessage }, 'warning', 6000);
}
} else {
showToast(`Successfully moved ${result.success_count} ${this.apiConfig.config.displayName}s`, 'success');
showToast('toast.api.bulkMoveSuccess', {
successCount: result.success_count,
type: this.apiConfig.config.displayName
}, 'success');
}
// Return the results array with original_file_path and new_file_path
@@ -931,12 +938,12 @@ export class BaseModelApiClient {
// Wait for the operation to complete via WebSocket
await operationComplete;
showToast('Successfully downloaded example images!', 'success');
showToast('toast.api.exampleImagesDownloadSuccess', {}, 'success');
return true;
} catch (error) {
console.error('Error downloading example images:', error);
showToast(`Failed to download example images: ${error.message}`, 'error');
showToast('toast.api.exampleImagesDownloadFailed', { message: error.message }, 'error');
throw error;
} finally {
if (ws) {

View File

@@ -1,5 +1,4 @@
import { BaseModelApiClient } from './baseModelApi.js';
import { showToast } from '../utils/uiHelpers.js';
/**
* Checkpoint-specific API client

View File

@@ -1,5 +1,4 @@
import { BaseModelApiClient } from './baseModelApi.js';
import { showToast } from '../utils/uiHelpers.js';
/**
* Embedding-specific API client

View File

@@ -47,7 +47,7 @@ export class CheckpointsControls extends PageControls {
// No clearCustomFilter implementation is needed for checkpoints
// as custom filters are currently only used for LoRAs
clearCustomFilter: async () => {
showToast('No custom filter to clear', 'info');
showToast('toast.filters.noCustomFilterToClear', {}, 'info');
}
};

View File

@@ -47,7 +47,7 @@ export class EmbeddingsControls extends PageControls {
// No clearCustomFilter implementation is needed for embeddings
// as custom filters are currently only used for LoRAs
clearCustomFilter: async () => {
showToast('No custom filter to clear', 'info');
showToast('toast.filters.noCustomFilterToClear', {}, 'info');
}
};

View File

@@ -83,8 +83,7 @@ export function setupModelNameEditing(filePath) {
sel.removeAllRanges();
sel.addRange(range);
const text = translate('modelMetadata.validation.nameTooLong', {}, 'Model name is limited to 100 characters');
showToast(text, 'warning');
showToast('toast.models.nameTooLong', {}, 'warning');
}
});
@@ -99,7 +98,7 @@ export function setupModelNameEditing(filePath) {
if (!newModelName) {
// Restore original value if empty
this.textContent = originalValue;
showToast('Model name cannot be empty', 'error');
showToast('toast.models.nameCannotBeEmpty', {}, 'error');
exitEditMode();
return;
}
@@ -116,11 +115,11 @@ export function setupModelNameEditing(filePath) {
await getModelApiClient().saveModelMetadata(filePath, { model_name: newModelName });
showToast('Model name updated successfully', 'success');
showToast('toast.models.nameUpdatedSuccessfully', {}, 'success');
} catch (error) {
console.error('Error updating model name:', error);
this.textContent = originalValue; // Restore original model name
showToast('Failed to update model name', 'error');
showToast('toast.models.nameUpdateFailed', {}, 'error');
} finally {
exitEditMode();
}
@@ -302,9 +301,9 @@ async function saveBaseModel(filePath, originalValue) {
try {
await getModelApiClient().saveModelMetadata(filePath, { base_model: newBaseModel });
showToast('Base model updated successfully', 'success');
showToast('toast.models.baseModelUpdated', {}, 'success');
} catch (error) {
showToast('Failed to update base model', 'error');
showToast('toast.models.baseModelUpdateFailed', {}, 'error');
}
}
@@ -390,7 +389,7 @@ export function setupFileNameEditing(filePath) {
sel.addRange(range);
}
showToast('Invalid characters removed from filename', 'warning');
showToast('toast.models.invalidCharactersRemoved', {}, 'warning');
}
});
@@ -405,7 +404,7 @@ export function setupFileNameEditing(filePath) {
if (!newFileName) {
// Restore original value if empty
this.textContent = originalValue;
showToast('File name cannot be empty', 'error');
showToast('toast.models.filenameCannotBeEmpty', {}, 'error');
exitEditMode();
return;
}
@@ -424,7 +423,7 @@ export function setupFileNameEditing(filePath) {
} catch (error) {
console.error('Error renaming file:', error);
this.textContent = originalValue; // Restore original file name
showToast(`Failed to rename file: ${error.message}`, 'error');
showToast('toast.models.renameFailed', { message: error.message }, 'error');
} finally {
exitEditMode();
}

View File

@@ -26,7 +26,7 @@ async function fetchTrainedWords(filePath) {
}
} catch (error) {
console.error('Error fetching trained words:', error);
showToast('Could not load trained words', 'error');
showToast('toast.triggerWords.loadFailed', {}, 'error');
return { trainedWords: [], classTokens: null };
}
}
@@ -499,21 +499,21 @@ function addNewTriggerWord(word) {
// Validation: Check length
if (word.split(/\s+/).length > 30) {
showToast('Trigger word should not exceed 30 words', 'error');
showToast('toast.triggerWords.tooLong', {}, 'error');
return;
}
// Validation: Check total number
const currentTags = tagsContainer.querySelectorAll('.trigger-word-tag');
if (currentTags.length >= 30) {
showToast('Maximum 30 trigger words allowed', 'error');
showToast('toast.triggerWords.tooMany', {}, 'error');
return;
}
// Validation: Check for duplicates
const existingWords = Array.from(currentTags).map(tag => tag.dataset.word);
if (existingWords.includes(word)) {
showToast('This trigger word already exists', 'error');
showToast('toast.triggerWords.alreadyExists', {}, 'error');
return;
}
@@ -628,10 +628,10 @@ async function saveTriggerWords() {
if (tagsContainer) tagsContainer.style.display = 'none';
}
showToast('Trigger words updated successfully', 'success');
showToast('toast.triggerWords.updateSuccess', {}, 'success');
} catch (error) {
console.error('Error saving trigger words:', error);
showToast('Failed to update trigger words', 'error');
showToast('toast.triggerWords.updateFailed', {}, 'error');
}
}
@@ -644,6 +644,6 @@ window.copyTriggerWord = async function(word) {
await copyToClipboard(word, 'Trigger word copied');
} catch (err) {
console.error('Copy failed:', err);
showToast('Copy failed', 'error');
showToast('toast.triggerWords.copyFailed', {}, 'error');
}
};

View File

@@ -10,7 +10,7 @@ import { bulkManager } from './managers/BulkManager.js';
import { exampleImagesManager } from './managers/ExampleImagesManager.js';
import { helpManager } from './managers/HelpManager.js';
import { bannerService } from './managers/BannerService.js';
import { showToast, initTheme, initBackToTop } from './utils/uiHelpers.js';
import { initTheme, initBackToTop } from './utils/uiHelpers.js';
import { initializeInfiniteScroll } from './utils/infiniteScroll.js';
import { migrateStorageItems } from './utils/storageHelpers.js';
import { i18n } from './i18n/index.js';
@@ -75,11 +75,6 @@ export class AppCore {
return body.dataset.page || 'unknown';
}
// Show toast messages
showToast(key, params = {}, type = 'info') {
showToast(key, params, type);
}
// Initialize common UI features based on page type
initializePageFeatures() {
const pageType = this.getPageType();

View File

@@ -350,11 +350,11 @@ export class BulkManager {
if (missingLoras.length > 0) {
console.warn('Missing metadata for some selected loras:', missingLoras);
showToast(`Missing data for ${missingLoras.length} LoRAs`, 'warning');
showToast('toast.loras.missingDataForLoras', { count: missingLoras.length }, 'warning');
}
if (loraSyntaxes.length === 0) {
showToast('No valid LoRAs to send', 'error');
showToast('toast.loras.noValidLorasToSend', {}, 'error');
return;
}
@@ -363,7 +363,7 @@ export class BulkManager {
showBulkDeleteModal() {
if (state.selectedModels.size === 0) {
showToast('No models selected', 'warning');
showToast('toast.models.noModelsSelected', {}, 'warning');
return;
}
@@ -377,7 +377,7 @@ export class BulkManager {
async confirmBulkDelete() {
if (state.selectedModels.size === 0) {
showToast('No models selected', 'warning');
showToast('toast.models.noModelsSelected', {}, 'warning');
modalManager.closeModal('bulkDeleteModal');
return;
}
@@ -392,7 +392,10 @@ export class BulkManager {
if (result.success) {
const currentConfig = MODEL_CONFIG[state.currentPageType];
showToast(`Successfully deleted ${result.deleted_count} ${currentConfig.displayName.toLowerCase()}(s)`, 'success');
showToast('toast.models.deletedSuccessfully', {
count: result.deleted_count,
type: currentConfig.displayName.toLowerCase()
}, 'success');
filePaths.forEach(path => {
state.virtualScroller.removeItemByFilePath(path);
@@ -403,11 +406,11 @@ export class BulkManager {
window.modelDuplicatesManager.updateDuplicatesBadgeAfterRefresh();
}
} else {
showToast(`Error: ${result.error || 'Failed to delete models'}`, 'error');
showToast('toast.models.deleteFailed', { error: result.error || 'Failed to delete models' }, 'error');
}
} catch (error) {
console.error('Error during bulk delete:', error);
showToast('Failed to delete models', 'error');
showToast('toast.models.deleteFailedGeneral', {}, 'error');
}
}
@@ -538,7 +541,7 @@ export class BulkManager {
selectAllVisibleModels() {
if (!state.virtualScroller || !state.virtualScroller.items) {
showToast('Unable to select all items', 'error');
showToast('toast.bulk.unableToSelectAll', {}, 'error');
return;
}
@@ -565,7 +568,10 @@ export class BulkManager {
const newlySelected = state.selectedModels.size - oldCount;
const currentConfig = MODEL_CONFIG[state.currentPageType];
showToast(`Selected ${newlySelected} additional ${currentConfig.displayName.toLowerCase()}(s)`, 'success');
showToast('toast.models.selectedAdditional', {
count: newlySelected,
type: currentConfig.displayName.toLowerCase()
}, 'success');
if (this.isStripVisible) {
this.updateThumbnailStrip();
@@ -574,7 +580,7 @@ export class BulkManager {
async refreshAllMetadata() {
if (state.selectedModels.size === 0) {
showToast('No models selected', 'warning');
showToast('toast.models.noModelsSelected', {}, 'warning');
return;
}
@@ -610,7 +616,7 @@ export class BulkManager {
} catch (error) {
console.error('Error during bulk metadata refresh:', error);
showToast('Failed to refresh metadata', 'error');
showToast('toast.models.refreshMetadataFailed', {}, 'error');
}
}
}

View File

@@ -321,7 +321,7 @@ export class FilterManager {
await getModelApiClient().loadMoreWithVirtualScroll(true, true);
}
showToast(`Filters cleared`, 'info');
showToast('toast.filters.cleared', {}, 'info');
}
loadFiltersFromStorage() {

View File

@@ -261,7 +261,7 @@ export class ImportManager {
this.updateTargetPath();
} catch (error) {
showToast(error.message, 'error');
showToast('toast.import.importFailed', { message: error.message }, 'error');
}
}
@@ -350,11 +350,11 @@ export class ImportManager {
await this.folderTreeManager.loadTree(treeData.tree);
} else {
console.error('Failed to fetch folder tree:', treeData.error);
showToast('Failed to load folder tree', 'error');
showToast('toast.import.folderTreeFailed', {}, 'error');
}
} catch (error) {
console.error('Error initializing folder tree:', error);
showToast('Error loading folder tree', 'error');
showToast('toast.import.folderTreeError', {}, 'error');
}
}

View File

@@ -45,7 +45,7 @@ class MoveManager {
if (filePath === 'bulk') {
const selectedPaths = Array.from(state.selectedModels);
if (selectedPaths.length === 0) {
showToast('No models selected', 'warning');
showToast('toast.models.noModelsSelected', {}, 'warning');
return;
}
this.bulkFilePaths = selectedPaths;
@@ -116,7 +116,7 @@ class MoveManager {
} catch (error) {
console.error(`Error fetching ${modelConfig.displayName.toLowerCase()} roots or folders:`, error);
showToast(error.message, 'error');
showToast('toast.models.moveFailed', { message: error.message }, 'error');
}
}
@@ -131,11 +131,11 @@ class MoveManager {
await this.folderTreeManager.loadTree(treeData.tree);
} else {
console.error('Failed to fetch folder tree:', treeData.error);
showToast('Failed to load folder tree', 'error');
showToast('toast.import.folderTreeFailed', {}, 'error');
}
} catch (error) {
console.error('Error initializing folder tree:', error);
showToast('Error loading folder tree', 'error');
showToast('toast.import.folderTreeError', {}, 'error');
}
}
@@ -163,7 +163,7 @@ class MoveManager {
const config = apiClient.apiConfig.config;
if (!selectedRoot) {
showToast(`Please select a ${config.displayName.toLowerCase()} root directory`, 'error');
showToast('toast.models.pleaseSelectRoot', { type: config.displayName.toLowerCase() }, 'error');
return;
}
@@ -236,7 +236,7 @@ class MoveManager {
} catch (error) {
console.error('Error moving model(s):', error);
showToast('Failed to move model(s): ' + error.message, 'error');
showToast('toast.models.moveFailed', { message: error.message }, 'error');
}
}
}

View File

@@ -314,7 +314,7 @@ export class SettingsManager {
} catch (error) {
console.error('Error loading LoRA roots:', error);
showToast('Failed to load LoRA roots: ' + error.message, 'error');
showToast('toast.settings.loraRootsFailed', { message: error.message }, 'error');
}
}
@@ -353,7 +353,7 @@ export class SettingsManager {
} catch (error) {
console.error('Error loading checkpoint roots:', error);
showToast('Failed to load checkpoint roots: ' + error.message, 'error');
showToast('toast.settings.checkpointRootsFailed', { message: error.message }, 'error');
}
}
@@ -392,7 +392,7 @@ export class SettingsManager {
} catch (error) {
console.error('Error loading embedding roots:', error);
showToast('Failed to load embedding roots: ' + error.message, 'error');
showToast('toast.settings.embeddingRootsFailed', { message: error.message }, 'error');
}
}
@@ -560,14 +560,17 @@ export class SettingsManager {
// Show success toast
const mappingCount = Object.keys(state.global.settings.base_model_path_mappings).length;
if (mappingCount > 0) {
showToast(`Base model path mappings updated (${mappingCount} mapping${mappingCount !== 1 ? 's' : ''})`, 'success');
showToast('toast.settings.mappingsUpdated', {
count: mappingCount,
plural: mappingCount !== 1 ? 's' : ''
}, 'success');
} else {
showToast('Base model path mappings cleared', 'success');
showToast('toast.settings.mappingsCleared', {}, 'success');
}
} catch (error) {
console.error('Error saving base model mappings:', error);
showToast('Failed to save base model mappings: ' + error.message, 'error');
showToast('toast.settings.mappingSaveFailed', { message: error.message }, 'error');
}
}
@@ -744,11 +747,11 @@ export class SettingsManager {
throw new Error('Failed to save download path templates');
}
showToast('Download path templates updated', 'success');
showToast('toast.settings.downloadTemplatesUpdated', {}, 'success');
} catch (error) {
console.error('Error saving download path templates:', error);
showToast('Failed to save download path templates: ' + error.message, 'error');
showToast('toast.settings.downloadTemplatesFailed', { message: error.message }, 'error');
}
}
@@ -809,7 +812,7 @@ export class SettingsManager {
}
}
showToast(`Settings updated: ${settingKey.replace(/_/g, ' ')}`, 'success');
showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success');
// Apply frontend settings immediately
this.applyFrontendSettings();
@@ -830,11 +833,13 @@ export class SettingsManager {
// Recalculate layout when compact mode changes
if (settingKey === 'compact_mode' && state.virtualScroller) {
state.virtualScroller.calculateLayout();
showToast(`Compact Mode ${value ? 'enabled' : 'disabled'}`, 'success');
showToast('toast.settings.compactModeToggled', {
state: value ? 'toast.settings.compactModeEnabled' : 'toast.settings.compactModeDisabled'
}, 'success');
}
} catch (error) {
showToast('Failed to save setting: ' + error.message, 'error');
showToast('toast.settings.settingSaveFailed', { message: error.message }, 'error');
}
}
@@ -888,7 +893,7 @@ export class SettingsManager {
throw new Error('Failed to save setting');
}
showToast(`Settings updated: ${settingKey.replace(/_/g, ' ')}`, 'success');
showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success');
}
// Apply frontend settings immediately
@@ -902,11 +907,11 @@ export class SettingsManager {
if (value === 'medium') densityName = "Medium";
if (value === 'compact') densityName = "Compact";
showToast(`Display Density set to ${densityName}`, 'success');
showToast('toast.settings.displayDensitySet', { density: densityName }, 'success');
}
} catch (error) {
showToast('Failed to save setting: ' + error.message, 'error');
showToast('toast.settings.settingSaveFailed', { message: error.message }, 'error');
}
}
@@ -945,10 +950,10 @@ export class SettingsManager {
throw new Error('Failed to save setting');
}
showToast(`Settings updated: ${settingKey.replace(/_/g, ' ')}`, 'success');
showToast('toast.settings.settingsUpdated', { setting: settingKey.replace(/_/g, ' ') }, 'success');
} catch (error) {
showToast('Failed to save setting: ' + error.message, 'error');
showToast('toast.settings.settingSaveFailed', { message: error.message }, 'error');
}
}
@@ -984,7 +989,7 @@ export class SettingsManager {
window.location.reload();
} catch (error) {
showToast('Failed to change language: ' + error.message, 'error');
showToast('toast.settings.languageChangeFailed', { message: error.message }, 'error');
}
}
@@ -1019,15 +1024,15 @@ export class SettingsManager {
const result = await response.json();
if (result.success) {
showToast('Cache files have been cleared successfully. Cache will rebuild on next action.', 'success');
showToast('toast.settings.cacheCleared', {}, 'success');
} else {
showToast(`Failed to clear cache: ${result.error}`, 'error');
showToast('toast.settings.cacheClearFailed', { error: result.error }, 'error');
}
// Close the confirmation modal
modalManager.closeModal('clearCacheModal');
} catch (error) {
showToast(`Error clearing cache: ${error.message}`, 'error');
showToast('toast.settings.cacheClearError', { message: error.message }, 'error');
modalManager.closeModal('clearCacheModal');
}
}

View File

@@ -156,7 +156,7 @@ export class ImageProcessor {
async uploadAndAnalyzeImage() {
if (!this.importManager.recipeImage) {
showToast('Please select an image first', 'error');
showToast('toast.import.selectImageFirst', {}, 'error');
return;
}

View File

@@ -406,7 +406,7 @@ export class RecipeDataManager {
proceedFromDetails() {
// Validate recipe name
if (!this.importManager.recipeName) {
showToast('Please enter a recipe name', 'error');
showToast('toast.import.enterRecipeName', {}, 'error');
return;
}