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:
Will Miao
2025-08-30 21:41:48 +08:00
parent f6709a55c3
commit 52acbd954a
36 changed files with 4662 additions and 3819 deletions

170
i18n_migration_summary.md Normal file
View File

@@ -0,0 +1,170 @@
# i18n System Migration Complete
## 概要 (Summary)
成功完成了从JavaScript ES6模块到JSON格式的国际化系统迁移包含完整的多语言翻译和代码更新。
Successfully completed the migration from JavaScript ES6 modules to JSON format for the internationalization system, including complete multilingual translations and code updates.
## 完成的工作 (Completed Work)
### 1. 文件结构重组 (File Structure Reorganization)
- **新建目录**: `/locales/` - 集中存放所有JSON翻译文件
- **移除目录**: `/static/js/i18n/locales/` - 删除了旧的JavaScript文件
### 2. 格式转换 (Format Conversion)
- **转换前**: ES6模块格式 (`export const en = { ... }`)
- **转换后**: 标准JSON格式 (`{ ... }`)
- **支持语言**: 9种语言完全转换
- English (en)
- 简体中文 (zh-CN)
- 繁體中文 (zh-TW)
- 日本語 (ja)
- Русский (ru)
- Deutsch (de)
- Français (fr)
- Español (es)
- 한국어 (ko)
### 3. 翻译完善 (Translation Completion)
- **翻译条目**: 每种语言386个翻译键值对
- **覆盖范围**: 完整覆盖所有UI元素
- **质量保证**: 所有翻译键在各语言间保持一致
### 4. JavaScript代码更新 (JavaScript Code Updates)
#### 主要修改文件: `static/js/i18n/index.js`
```javascript
// 旧版本: 静态导入
import { en } from './locales/en.js';
// 新版本: 动态JSON加载
async loadLocale(locale) {
const response = await fetch(`/locales/${locale}.json`);
return await response.json();
}
```
#### 核心功能更新:
- **构造函数**: 从静态导入改为配置驱动
- **语言加载**: 异步JSON获取机制
- **初始化**: 支持Promise-based的异步初始化
- **错误处理**: 增强的回退机制到英语
- **向后兼容**: 保持现有API接口不变
### 5. Python服务端更新 (Python Server-side Updates)
#### 修改文件: `py/services/server_i18n.py`
```python
# 旧版本: 解析JavaScript文件
def _load_locale_file(self, path, filename, locale_code):
# 复杂的JS到JSON转换逻辑
# 新版本: 直接加载JSON
def _load_locale_file(self, path, filename, locale_code):
with open(file_path, 'r', encoding='utf-8') as f:
translations = json.load(f)
```
#### 路径更新:
- **旧路径**: `static/js/i18n/locales/*.js`
- **新路径**: `locales/*.json`
### 6. 服务器路由配置 (Server Route Configuration)
#### 修改文件: `standalone.py`
```python
# 新增静态路由服务JSON文件
app.router.add_static('/locales', locales_path)
```
## 技术架构 (Technical Architecture)
### 前端 (Frontend)
```
Browser → JavaScript i18n Manager → fetch('/locales/{lang}.json') → JSON Response
```
### 后端 (Backend)
```
Python Server → ServerI18nManager → Direct JSON loading → Template Rendering
```
### 文件组织 (File Organization)
```
ComfyUI-Lora-Manager/
├── locales/ # 新的JSON翻译文件目录
│ ├── en.json # 英语翻译 (基准)
│ ├── zh-CN.json # 简体中文翻译
│ ├── zh-TW.json # 繁体中文翻译
│ ├── ja.json # 日语翻译
│ ├── ru.json # 俄语翻译
│ ├── de.json # 德语翻译
│ ├── fr.json # 法语翻译
│ ├── es.json # 西班牙语翻译
│ └── ko.json # 韩语翻译
├── static/js/i18n/
│ └── index.js # 更新的JavaScript i18n管理器
└── py/services/
└── server_i18n.py # 更新的Python服务端i18n
```
## 测试验证 (Testing & Validation)
### 测试脚本: `test_i18n.py`
```bash
🚀 Testing updated i18n system...
✅ All JSON locale files are valid (9 languages)
✅ Server-side i18n system working correctly
✅ All languages have complete translations (386 keys each)
🎉 All tests passed!
```
### 验证内容:
1. **JSON文件完整性**: 所有文件格式正确,语法有效
2. **翻译完整性**: 各语言翻译键值一致,无缺失
3. **服务端功能**: Python i18n服务正常加载和翻译
4. **参数插值**: 动态参数替换功能正常
## 优势与改进 (Benefits & Improvements)
### 1. 维护性提升
- **简化格式**: JSON比JavaScript对象更易于编辑和维护
- **工具支持**: 更好的编辑器语法高亮和验证支持
- **版本控制**: 更清晰的diff显示便于追踪更改
### 2. 性能优化
- **按需加载**: 只加载当前所需语言,减少初始加载时间
- **缓存友好**: JSON文件可以被浏览器和CDN更好地缓存
- **压缩效率**: JSON格式压缩率通常更高
### 3. 开发体验
- **动态切换**: 支持运行时语言切换,无需重新加载页面
- **易于扩展**: 添加新语言只需增加JSON文件
- **调试友好**: 更容易定位翻译问题和缺失键
### 4. 部署便利
- **静态资源**: JSON文件可以作为静态资源部署
- **CDN支持**: 可以通过CDN分发翻译文件
- **版本管理**: 更容易管理不同版本的翻译
## 兼容性保证 (Compatibility Assurance)
- **API兼容**: 所有现有的JavaScript API保持不变
- **调用方式**: 现有代码无需修改即可工作
- **错误处理**: 增强的回退机制确保用户体验
- **性能**: 新系统性能与旧系统相当或更好
## 后续建议 (Future Recommendations)
1. **监控**: 部署后监控翻译加载性能和错误率
2. **优化**: 考虑实施翻译缓存策略以进一步提升性能
3. **扩展**: 可以考虑添加翻译管理界面,便于非技术人员更新翻译
4. **自动化**: 实施CI/CD流程自动验证翻译完整性
---
**迁移完成时间**: 2024年
**影响文件数量**: 21个文件 (9个新JSON + 2个JS更新 + 1个Python更新 + 1个服务器配置)
**翻译键总数**: 386个 × 9种语言 = 3,474个翻译条目
**测试状态**: ✅ 全部通过

453
locales/de.json Normal file
View File

@@ -0,0 +1,453 @@
{
"common": {
"file": "Datei",
"folder": "Ordner",
"name": "Name",
"size": "Größe",
"date": "Datum",
"type": "Typ",
"path": "Pfad",
"fileSize": {
"zero": "0 Bytes",
"bytes": "Bytes",
"kb": "KB",
"mb": "MB",
"gb": "GB",
"tb": "TB"
},
"actions": {
"save": "Speichern",
"cancel": "Abbrechen",
"delete": "Löschen",
"edit": "Bearbeiten",
"copy": "Kopieren",
"move": "Verschieben",
"refresh": "Aktualisieren",
"download": "Herunterladen",
"upload": "Hochladen",
"search": "Suchen",
"filter": "Filter",
"sort": "Sortieren",
"select": "Auswählen",
"selectAll": "Alle auswählen",
"deselectAll": "Auswahl aufheben",
"confirm": "Bestätigen",
"close": "Schließen",
"back": "Zurück",
"next": "Weiter",
"previous": "Vorherige",
"view": "Ansicht",
"preview": "Vorschau",
"details": "Details",
"backToTop": "Nach oben",
"settings": "Einstellungen",
"help": "Hilfe",
"about": "Über"
},
"status": {
"loading": "Wird geladen...",
"saving": "Wird gespeichert...",
"saved": "Gespeichert",
"error": "Fehler",
"success": "Erfolgreich",
"warning": "Warnung",
"info": "Information",
"processing": "Wird verarbeitet...",
"completed": "Abgeschlossen",
"failed": "Fehlgeschlagen",
"cancelled": "Abgebrochen",
"pending": "Wartend",
"ready": "Bereit"
},
"language": {
"current": "Sprache",
"select": "Sprache auswählen",
"select_help": "Wählen Sie Ihre bevorzugte Sprache für die Benutzeroberfläche",
"english": "Englisch",
"chinese_simplified": "Chinesisch (Vereinfacht)",
"chinese_traditional": "Chinesisch (Traditionell)",
"russian": "Russisch",
"german": "Deutsch",
"japanese": "Japanisch",
"korean": "Koreanisch",
"french": "Französisch",
"spanish": "Spanisch"
}
},
"header": {
"appTitle": "LoRA Manager",
"navigation": {
"loras": "LoRAs",
"recipes": "Rezepte",
"checkpoints": "Checkpoints",
"embeddings": "Embeddings",
"statistics": "Statistiken"
},
"search": {
"placeholder": "Suchen...",
"placeholders": {
"loras": "LoRAs suchen...",
"recipes": "Rezepte suchen...",
"checkpoints": "Checkpoints suchen...",
"embeddings": "Embeddings suchen..."
},
"options": "Suchoptionen",
"searchIn": "Suchen in:",
"notAvailable": "Suche auf der Statistikseite nicht verfügbar",
"filters": {
"filename": "Dateiname",
"modelname": "Modellname",
"tags": "Tags",
"creator": "Ersteller",
"title": "Rezept-Titel",
"loraName": "LoRA Dateiname",
"loraModel": "LoRA Modellname"
}
},
"filter": {
"title": "Modelle filtern",
"baseModel": "Basis-Modell",
"modelTags": "Tags (Top 20)",
"clearAll": "Alle Filter löschen"
},
"theme": {
"toggle": "Theme umschalten",
"switchToLight": "Zu hellem Theme wechseln",
"switchToDark": "Zu dunklem Theme wechseln",
"switchToAuto": "Zu automatischem Theme wechseln"
}
},
"loras": {
"title": "LoRA Modelle",
"controls": {
"sort": {
"title": "Modelle sortieren nach...",
"name": "Name",
"nameAsc": "A - Z",
"nameDesc": "Z - A",
"date": "Hinzugefügt am",
"dateDesc": "Neueste",
"dateAsc": "Älteste",
"size": "Dateigröße",
"sizeDesc": "Größte",
"sizeAsc": "Kleinste"
},
"refresh": {
"title": "Modellliste aktualisieren",
"quick": "Schnelle Aktualisierung (inkrementell)",
"full": "Vollständiger Neuaufbau (komplett)"
},
"fetch": "Von Civitai abrufen",
"download": "Von URL herunterladen",
"bulk": "Massenoperationen",
"duplicates": "Duplikate finden",
"favorites": "Nur Favoriten anzeigen"
},
"bulkOperations": {
"title": "Massenoperationen",
"selected": "{count} ausgewählt",
"sendToWorkflow": "Alle ausgewählten LoRAs an Workflow senden",
"copyAll": "Syntax aller ausgewählten LoRAs kopieren",
"refreshAll": "CivitAI-Metadaten für ausgewählte Modelle aktualisieren",
"moveAll": "Ausgewählte Modelle in Ordner verschieben",
"deleteAll": "Ausgewählte Modelle löschen",
"clear": "Auswahl löschen"
},
"contextMenu": {
"refreshMetadata": "Civitai-Daten aktualisieren",
"relinkCivitai": "Mit Civitai neu verknüpfen",
"copySyntax": "LoRA-Syntax kopieren",
"copyFilename": "Modell-Dateiname kopieren",
"copyRecipeSyntax": "Rezept-Syntax kopieren",
"sendToWorkflowAppend": "An Workflow senden (anhängen)",
"sendToWorkflowReplace": "An Workflow senden (ersetzen)",
"openExamplesFolder": "Beispiel-Ordner öffnen",
"downloadExamples": "Beispielbilder herunterladen",
"replacePreview": "Vorschau ersetzen",
"setContentRating": "Inhaltsbewertung festlegen",
"moveToFolder": "In Ordner verschieben",
"excludeModel": "Modell ausschließen",
"deleteModel": "Modell löschen",
"shareRecipe": "Rezept teilen",
"viewAllLoras": "Alle LoRAs anzeigen",
"downloadMissingLoras": "Fehlende LoRAs herunterladen",
"deleteRecipe": "Rezept löschen"
},
"modal": {
"title": "LoRA Details",
"tabs": {
"examples": "Beispiele",
"description": "Modellbeschreibung",
"recipes": "Rezepte"
},
"info": {
"filename": "Dateiname",
"modelName": "Modellname",
"baseModel": "Basis-Modell",
"fileSize": "Dateigröße",
"dateAdded": "Hinzugefügt am",
"triggerWords": "Auslösewörter",
"description": "Beschreibung",
"tags": "Tags",
"rating": "Bewertung",
"downloads": "Downloads",
"likes": "Likes",
"version": "Version"
},
"actions": {
"copyTriggerWords": "Auslösewörter kopieren",
"copyLoraName": "LoRA-Name kopieren",
"sendToWorkflow": "An Workflow senden",
"viewOnCivitai": "Auf Civitai anzeigen",
"downloadExamples": "Beispielbilder herunterladen"
}
}
},
"recipes": {
"title": "LoRA Rezepte",
"controls": {
"import": "Rezept importieren",
"refresh": {
"title": "Rezeptliste aktualisieren"
},
"duplicates": {
"title": "Doppelte Rezepte finden"
},
"filteredByLora": "Nach LoRA gefiltert",
"create": "Rezept erstellen",
"export": "Ausgewählte exportieren",
"downloadMissing": "Fehlende LoRAs herunterladen"
},
"duplicates": {
"found": "{count} doppelte Gruppen gefunden",
"keepLatest": "Neueste Versionen behalten",
"deleteSelected": "Ausgewählte löschen"
},
"card": {
"author": "Autor",
"loras": "{count} LoRAs",
"tags": "Tags",
"actions": {
"sendToWorkflow": "An Workflow senden",
"edit": "Rezept bearbeiten",
"duplicate": "Rezept duplizieren",
"export": "Rezept exportieren",
"delete": "Rezept löschen"
}
}
},
"checkpoints": {
"title": "Checkpoint-Modelle",
"info": {
"filename": "Dateiname",
"modelName": "Modellname",
"baseModel": "Basis-Modell",
"fileSize": "Dateigröße",
"dateAdded": "Hinzugefügt am"
}
},
"embeddings": {
"title": "Embedding-Modelle",
"info": {
"filename": "Dateiname",
"modelName": "Modellname",
"triggerWords": "Auslösewörter",
"fileSize": "Dateigröße",
"dateAdded": "Hinzugefügt am"
}
},
"sidebar": {
"modelRoot": "Modell-Wurzel",
"collapseAll": "Alle Ordner einklappen",
"pinToggle": "Seitenleiste anheften/lösen"
},
"statistics": {
"title": "Statistiken",
"tabs": {
"overview": "Übersicht",
"usage": "Nutzungsanalyse",
"collection": "Sammlung",
"storage": "Speicher",
"insights": "Erkenntnisse"
},
"overview": {
"title": "Übersicht",
"totalLoras": "LoRAs gesamt",
"totalCheckpoints": "Checkpoints gesamt",
"totalEmbeddings": "Embeddings gesamt",
"totalSize": "Gesamtgröße",
"favoriteModels": "Lieblingsmodelle"
},
"charts": {
"modelsByType": "Modelle nach Typ",
"modelsByBaseModel": "Modelle nach Basis-Modell",
"modelsBySize": "Modelle nach Dateigröße",
"modelsAddedOverTime": "Modelle über Zeit hinzugefügt"
}
},
"modals": {
"delete": {
"title": "Löschung bestätigen",
"message": "Sind Sie sicher, dass Sie dieses Modell löschen möchten?",
"warningMessage": "Diese Aktion kann nicht rückgängig gemacht werden.",
"confirm": "Löschen",
"cancel": "Abbrechen"
},
"exclude": {
"title": "Modell ausschließen",
"message": "Sind Sie sicher, dass Sie dieses Modell aus der Bibliothek ausschließen möchten?",
"confirm": "Ausschließen",
"cancel": "Abbrechen"
},
"download": {
"title": "Modell von URL herunterladen",
"url": "Civitai URL",
"placeholder": "https://civitai.com/models/...",
"locationPreview": "Download-Ort Vorschau",
"useDefaultPath": "Standardpfad verwenden",
"useDefaultPathTooltip": "Wenn aktiviert, werden Dateien automatisch mit konfigurierten Pfad-Vorlagen organisiert",
"selectRootDirectory": "Wurzelverzeichnis auswählen",
"download": "Herunterladen",
"cancel": "Abbrechen"
},
"move": {
"title": "Modelle verschieben",
"selectFolder": "Zielordner auswählen",
"createFolder": "Neuen Ordner erstellen",
"folderName": "Ordnername",
"move": "Verschieben",
"cancel": "Abbrechen"
},
"contentRating": {
"title": "Inhaltsbewertung festlegen",
"current": "Aktuell",
"levels": {
"pg": "Alle Altersgruppen",
"pg13": "Ab 13 Jahren",
"r": "Eingeschränkt",
"x": "Nur Erwachsene",
"xxx": "Explizit"
}
}
},
"errors": {
"general": "Ein Fehler ist aufgetreten",
"networkError": "Netzwerkfehler. Bitte überprüfen Sie Ihre Verbindung.",
"serverError": "Serverfehler. Bitte versuchen Sie es später erneut.",
"fileNotFound": "Datei nicht gefunden",
"invalidFile": "Ungültiges Dateiformat",
"uploadFailed": "Upload fehlgeschlagen",
"downloadFailed": "Download fehlgeschlagen",
"saveFailed": "Speichern fehlgeschlagen",
"loadFailed": "Laden fehlgeschlagen",
"deleteFailed": "Löschen fehlgeschlagen",
"moveFailed": "Verschieben fehlgeschlagen",
"copyFailed": "Kopieren fehlgeschlagen",
"fetchFailed": "Daten von Civitai konnten nicht abgerufen werden",
"invalidUrl": "Ungültiges URL-Format",
"missingPermissions": "Unzureichende Berechtigungen"
},
"success": {
"saved": "Erfolgreich gespeichert",
"deleted": "Erfolgreich gelöscht",
"moved": "Erfolgreich verschoben",
"copied": "Erfolgreich kopiert",
"downloaded": "Erfolgreich heruntergeladen",
"uploaded": "Erfolgreich hochgeladen",
"refreshed": "Erfolgreich aktualisiert",
"exported": "Erfolgreich exportiert",
"imported": "Erfolgreich importiert"
},
"keyboard": {
"navigation": "Tastaturnavigation:",
"shortcuts": {
"pageUp": "Eine Seite nach oben scrollen",
"pageDown": "Eine Seite nach unten scrollen",
"home": "Zum Anfang springen",
"end": "Zum Ende springen",
"bulkMode": "Massenmodus umschalten",
"search": "Suche fokussieren",
"escape": "Modal/Panel schließen"
}
},
"initialization": {
"title": "Initialisierung",
"message": "Vorbereitung Ihres Arbeitsbereichs...",
"status": "Initialisierung...",
"estimatingTime": "Zeit schätzen...",
"loras": {
"title": "LoRA Manager initialisieren",
"message": "LoRA-Cache wird gescannt und erstellt. Dies kann einige Minuten dauern..."
},
"checkpoints": {
"title": "Checkpoint Manager initialisieren",
"message": "Checkpoint-Cache wird gescannt und erstellt. Dies kann einige Minuten dauern..."
},
"embeddings": {
"title": "Embedding Manager initialisieren",
"message": "Embedding-Cache wird gescannt und erstellt. Dies kann einige Minuten dauern..."
},
"recipes": {
"title": "Rezept Manager initialisieren",
"message": "Rezepte werden geladen und verarbeitet. Dies kann einige Minuten dauern..."
},
"statistics": {
"title": "Statistiken initialisieren",
"message": "Modelldaten für Statistiken werden verarbeitet. Dies kann einige Minuten dauern..."
},
"tips": {
"title": "Tipps & Tricks",
"civitai": {
"title": "Civitai Integration",
"description": "Verbinden Sie Ihr Civitai-Konto: Besuchen Sie Profil Avatar → Einstellungen → API-Schlüssel → API-Schlüssel hinzufügen, dann fügen Sie ihn in die Lora Manager Einstellungen ein.",
"alt": "Civitai API Setup"
},
"download": {
"title": "Einfacher Download",
"description": "Verwenden Sie Civitai URLs, um neue Modelle schnell herunterzuladen und zu installieren.",
"alt": "Civitai Download"
},
"recipes": {
"title": "Rezepte speichern",
"description": "Erstellen Sie Rezepte, um Ihre Lieblings-Modellkombinationen für die zukünftige Verwendung zu speichern.",
"alt": "Rezepte"
},
"filter": {
"title": "Schnelle Filterung",
"description": "Filtern Sie Modelle nach Tags oder Basis-Modelltyp mit dem Filter-Button im Header.",
"alt": "Modelle filtern"
},
"search": {
"title": "Schnellsuche",
"description": "Drücken Sie Strg+F (Cmd+F auf Mac), um schnell in Ihrer aktuellen Ansicht zu suchen.",
"alt": "Schnellsuche"
}
},
"steps": {
"scanning": "Modelldateien scannen...",
"processing": "Metadaten verarbeiten...",
"building": "Cache erstellen...",
"finalizing": "Abschließen..."
}
},
"duplicates": {
"found": "{count} doppelte Gruppen gefunden",
"showNotification": "Duplikate-Benachrichtigung anzeigen",
"deleteSelected": "Ausgewählte löschen",
"exitMode": "Modus verlassen",
"help": {
"identicalHashes": "Identische Hashes bedeuten identische Modelldateien, auch wenn sie unterschiedliche Namen oder Vorschaubilder haben.",
"keepOne": "Behalten Sie nur eine Version (vorzugsweise mit besseren Metadaten/Vorschaubildern) und löschen Sie die anderen sicher."
}
},
"tooltips": {
"refresh": "Modellliste aktualisieren",
"bulkOperations": "Mehrere Modelle für Batch-Operationen auswählen",
"favorites": "Nur Lieblingsmodelle anzeigen",
"duplicates": "Doppelte Modelle finden und verwalten",
"search": "Modelle nach Name, Tags oder anderen Kriterien suchen",
"filter": "Modelle nach verschiedenen Kriterien filtern",
"sort": "Modelle nach verschiedenen Attributen sortieren",
"backToTop": "Zurück zum Seitenanfang scrollen"
}
}

453
locales/en.json Normal file
View File

@@ -0,0 +1,453 @@
{
"common": {
"file": "File",
"folder": "Folder",
"name": "Name",
"size": "Size",
"date": "Date",
"type": "Type",
"path": "Path",
"fileSize": {
"zero": "0 Bytes",
"bytes": "Bytes",
"kb": "KB",
"mb": "MB",
"gb": "GB",
"tb": "TB"
},
"actions": {
"save": "Save",
"cancel": "Cancel",
"delete": "Delete",
"edit": "Edit",
"copy": "Copy",
"move": "Move",
"refresh": "Refresh",
"download": "Download",
"upload": "Upload",
"search": "Search",
"filter": "Filter",
"sort": "Sort",
"select": "Select",
"selectAll": "Select All",
"deselectAll": "Deselect All",
"confirm": "Confirm",
"close": "Close",
"back": "Back",
"next": "Next",
"previous": "Previous",
"view": "View",
"preview": "Preview",
"details": "Details",
"backToTop": "Back to top",
"settings": "Settings",
"help": "Help",
"about": "About"
},
"status": {
"loading": "Loading...",
"saving": "Saving...",
"saved": "Saved",
"error": "Error",
"success": "Success",
"warning": "Warning",
"info": "Information",
"processing": "Processing...",
"completed": "Completed",
"failed": "Failed",
"cancelled": "Cancelled",
"pending": "Pending",
"ready": "Ready"
},
"language": {
"current": "Language",
"select": "Select Language",
"select_help": "Choose your preferred language for the interface",
"english": "English",
"chinese_simplified": "Chinese (Simplified)",
"chinese_traditional": "Chinese (Traditional)",
"russian": "Russian",
"german": "German",
"japanese": "Japanese",
"korean": "Korean",
"french": "French",
"spanish": "Spanish"
}
},
"header": {
"appTitle": "LoRA Manager",
"navigation": {
"loras": "LoRAs",
"recipes": "Recipes",
"checkpoints": "Checkpoints",
"embeddings": "Embeddings",
"statistics": "Stats"
},
"search": {
"placeholder": "Search...",
"placeholders": {
"loras": "Search LoRAs...",
"recipes": "Search recipes...",
"checkpoints": "Search checkpoints...",
"embeddings": "Search embeddings..."
},
"options": "Search Options",
"searchIn": "Search In:",
"notAvailable": "Search not available on statistics page",
"filters": {
"filename": "Filename",
"modelname": "Model Name",
"tags": "Tags",
"creator": "Creator",
"title": "Recipe Title",
"loraName": "LoRA Filename",
"loraModel": "LoRA Model Name"
}
},
"filter": {
"title": "Filter Models",
"baseModel": "Base Model",
"modelTags": "Tags (Top 20)",
"clearAll": "Clear All Filters"
},
"theme": {
"toggle": "Toggle theme",
"switchToLight": "Switch to light theme",
"switchToDark": "Switch to dark theme",
"switchToAuto": "Switch to auto theme"
}
},
"loras": {
"title": "LoRA Models",
"controls": {
"sort": {
"title": "Sort models by...",
"name": "Name",
"nameAsc": "A - Z",
"nameDesc": "Z - A",
"date": "Date Added",
"dateDesc": "Newest",
"dateAsc": "Oldest",
"size": "File Size",
"sizeDesc": "Largest",
"sizeAsc": "Smallest"
},
"refresh": {
"title": "Refresh model list",
"quick": "Quick Refresh (incremental)",
"full": "Full Rebuild (complete)"
},
"fetch": "Fetch from Civitai",
"download": "Download from URL",
"bulk": "Bulk Operations",
"duplicates": "Find Duplicates",
"favorites": "Show Favorites Only"
},
"bulkOperations": {
"title": "Bulk Operations",
"selected": "{count} selected",
"sendToWorkflow": "Send all selected LoRAs to workflow",
"copyAll": "Copy all selected LoRAs syntax",
"refreshAll": "Refresh CivitAI metadata for selected models",
"moveAll": "Move selected models to folder",
"deleteAll": "Delete selected models",
"clear": "Clear selection"
},
"contextMenu": {
"refreshMetadata": "Refresh Civitai Data",
"relinkCivitai": "Re-link to Civitai",
"copySyntax": "Copy LoRA Syntax",
"copyFilename": "Copy Model Filename",
"copyRecipeSyntax": "Copy Recipe Syntax",
"sendToWorkflowAppend": "Send to Workflow (Append)",
"sendToWorkflowReplace": "Send to Workflow (Replace)",
"openExamplesFolder": "Open Examples Folder",
"downloadExamples": "Download Example Images",
"replacePreview": "Replace Preview",
"setContentRating": "Set Content Rating",
"moveToFolder": "Move to Folder",
"excludeModel": "Exclude Model",
"deleteModel": "Delete Model",
"shareRecipe": "Share Recipe",
"viewAllLoras": "View All LoRAs",
"downloadMissingLoras": "Download Missing LoRAs",
"deleteRecipe": "Delete Recipe"
},
"modal": {
"title": "LoRA Details",
"tabs": {
"examples": "Examples",
"description": "Model Description",
"recipes": "Recipes"
},
"info": {
"filename": "Filename",
"modelName": "Model Name",
"baseModel": "Base Model",
"fileSize": "File Size",
"dateAdded": "Date Added",
"triggerWords": "Trigger Words",
"description": "Description",
"tags": "Tags",
"rating": "Rating",
"downloads": "Downloads",
"likes": "Likes",
"version": "Version"
},
"actions": {
"copyTriggerWords": "Copy trigger words",
"copyLoraName": "Copy LoRA name",
"sendToWorkflow": "Send to Workflow",
"viewOnCivitai": "View on Civitai",
"downloadExamples": "Download example images"
}
}
},
"recipes": {
"title": "LoRA Recipes",
"controls": {
"import": "Import Recipe",
"refresh": {
"title": "Refresh recipe list"
},
"duplicates": {
"title": "Find duplicate recipes"
},
"filteredByLora": "Filtered by LoRA",
"create": "Create Recipe",
"export": "Export Selected",
"downloadMissing": "Download Missing LoRAs"
},
"duplicates": {
"found": "Found {count} duplicate groups",
"keepLatest": "Keep Latest Versions",
"deleteSelected": "Delete Selected"
},
"card": {
"author": "Author",
"loras": "{count} LoRAs",
"tags": "Tags",
"actions": {
"sendToWorkflow": "Send to Workflow",
"edit": "Edit Recipe",
"duplicate": "Duplicate Recipe",
"export": "Export Recipe",
"delete": "Delete Recipe"
}
}
},
"checkpoints": {
"title": "Checkpoint Models",
"info": {
"filename": "Filename",
"modelName": "Model Name",
"baseModel": "Base Model",
"fileSize": "File Size",
"dateAdded": "Date Added"
}
},
"embeddings": {
"title": "Embedding Models",
"info": {
"filename": "Filename",
"modelName": "Model Name",
"triggerWords": "Trigger Words",
"fileSize": "File Size",
"dateAdded": "Date Added"
}
},
"sidebar": {
"modelRoot": "Model Root",
"collapseAll": "Collapse All Folders",
"pinToggle": "Pin/Unpin Sidebar"
},
"statistics": {
"title": "Statistics",
"tabs": {
"overview": "Overview",
"usage": "Usage Analysis",
"collection": "Collection",
"storage": "Storage",
"insights": "Insights"
},
"overview": {
"title": "Overview",
"totalLoras": "Total LoRAs",
"totalCheckpoints": "Total Checkpoints",
"totalEmbeddings": "Total Embeddings",
"totalSize": "Total Size",
"favoriteModels": "Favorite Models"
},
"charts": {
"modelsByType": "Models by Type",
"modelsByBaseModel": "Models by Base Model",
"modelsBySize": "Models by File Size",
"modelsAddedOverTime": "Models Added Over Time"
}
},
"modals": {
"delete": {
"title": "Confirm Deletion",
"message": "Are you sure you want to delete this model?",
"warningMessage": "This action cannot be undone.",
"confirm": "Delete",
"cancel": "Cancel"
},
"exclude": {
"title": "Exclude Model",
"message": "Are you sure you want to exclude this model from the library?",
"confirm": "Exclude",
"cancel": "Cancel"
},
"download": {
"title": "Download Model from URL",
"url": "Civitai URL",
"placeholder": "https://civitai.com/models/...",
"locationPreview": "Download Location Preview",
"useDefaultPath": "Use Default Path",
"useDefaultPathTooltip": "When enabled, files are automatically organized using configured path templates",
"selectRootDirectory": "Select a root directory",
"download": "Download",
"cancel": "Cancel"
},
"move": {
"title": "Move Models",
"selectFolder": "Select destination folder",
"createFolder": "Create new folder",
"folderName": "Folder name",
"move": "Move",
"cancel": "Cancel"
},
"contentRating": {
"title": "Set Content Rating",
"current": "Current",
"levels": {
"pg": "PG",
"pg13": "PG13",
"r": "R",
"x": "X",
"xxx": "XXX"
}
}
},
"errors": {
"general": "An error occurred",
"networkError": "Network error. Please check your connection.",
"serverError": "Server error. Please try again later.",
"fileNotFound": "File not found",
"invalidFile": "Invalid file format",
"uploadFailed": "Upload failed",
"downloadFailed": "Download failed",
"saveFailed": "Save failed",
"loadFailed": "Load failed",
"deleteFailed": "Delete failed",
"moveFailed": "Move failed",
"copyFailed": "Copy failed",
"fetchFailed": "Failed to fetch data from Civitai",
"invalidUrl": "Invalid URL format",
"missingPermissions": "Insufficient permissions"
},
"success": {
"saved": "Successfully saved",
"deleted": "Successfully deleted",
"moved": "Successfully moved",
"copied": "Successfully copied",
"downloaded": "Successfully downloaded",
"uploaded": "Successfully uploaded",
"refreshed": "Successfully refreshed",
"exported": "Successfully exported",
"imported": "Successfully imported"
},
"keyboard": {
"navigation": "Keyboard Navigation:",
"shortcuts": {
"pageUp": "Scroll up one page",
"pageDown": "Scroll down one page",
"home": "Jump to top",
"end": "Jump to bottom",
"bulkMode": "Toggle bulk mode",
"search": "Focus search",
"escape": "Close modal/panel"
}
},
"initialization": {
"title": "Initializing",
"message": "Preparing your workspace...",
"status": "Initializing...",
"estimatingTime": "Estimating time...",
"loras": {
"title": "Initializing LoRA Manager",
"message": "Scanning and building LoRA cache. This may take a few minutes..."
},
"checkpoints": {
"title": "Initializing Checkpoint Manager",
"message": "Scanning and building checkpoint cache. This may take a few minutes..."
},
"embeddings": {
"title": "Initializing Embedding Manager",
"message": "Scanning and building embedding cache. This may take a few minutes..."
},
"recipes": {
"title": "Initializing Recipe Manager",
"message": "Loading and processing recipes. This may take a few minutes..."
},
"statistics": {
"title": "Initializing Statistics",
"message": "Processing model data for statistics. This may take a few minutes..."
},
"tips": {
"title": "Tips & Tricks",
"civitai": {
"title": "Civitai Integration",
"description": "Connect your Civitai account: Visit Profile Avatar → Settings → API Keys → Add API Key, then paste it in Lora Manager settings.",
"alt": "Civitai API Setup"
},
"download": {
"title": "Easy Download",
"description": "Use Civitai URLs to quickly download and install new models.",
"alt": "Civitai Download"
},
"recipes": {
"title": "Save Recipes",
"description": "Create recipes to save your favorite model combinations for future use.",
"alt": "Recipes"
},
"filter": {
"title": "Fast Filtering",
"description": "Filter models by tags or base model type using the filter button in the header.",
"alt": "Filter Models"
},
"search": {
"title": "Quick Search",
"description": "Press Ctrl+F (Cmd+F on Mac) to quickly search within your current view.",
"alt": "Quick Search"
}
},
"steps": {
"scanning": "Scanning model files...",
"processing": "Processing metadata...",
"building": "Building cache...",
"finalizing": "Finalizing..."
}
},
"duplicates": {
"found": "Found {count} duplicate groups",
"showNotification": "Show Duplicates Notification",
"deleteSelected": "Delete Selected",
"exitMode": "Exit Mode",
"help": {
"identicalHashes": "Identical hashes mean identical model files, even if they have different names or previews.",
"keepOne": "Keep only one version (preferably with better metadata/previews) and safely delete the others."
}
},
"tooltips": {
"refresh": "Refresh the model list",
"bulkOperations": "Select multiple models for batch operations",
"favorites": "Show only favorite models",
"duplicates": "Find and manage duplicate models",
"search": "Search models by name, tags, or other criteria",
"filter": "Filter models by various criteria",
"sort": "Sort models by different attributes",
"backToTop": "Scroll back to top of page"
}
}

453
locales/es.json Normal file
View File

@@ -0,0 +1,453 @@
{
"common": {
"file": "Archivo",
"folder": "Carpeta",
"name": "Nombre",
"size": "Tamaño",
"date": "Fecha",
"type": "Tipo",
"path": "Ruta",
"fileSize": {
"zero": "0 Bytes",
"bytes": "Bytes",
"kb": "KB",
"mb": "MB",
"gb": "GB",
"tb": "TB"
},
"actions": {
"save": "Guardar",
"cancel": "Cancelar",
"delete": "Eliminar",
"edit": "Editar",
"copy": "Copiar",
"move": "Mover",
"refresh": "Actualizar",
"download": "Descargar",
"upload": "Subir",
"search": "Buscar",
"filter": "Filtrar",
"sort": "Ordenar",
"select": "Seleccionar",
"selectAll": "Seleccionar todo",
"deselectAll": "Deseleccionar todo",
"confirm": "Confirmar",
"close": "Cerrar",
"back": "Atrás",
"next": "Siguiente",
"previous": "Anterior",
"view": "Ver",
"preview": "Vista previa",
"details": "Detalles",
"backToTop": "Volver arriba",
"settings": "Configuración",
"help": "Ayuda",
"about": "Acerca de"
},
"status": {
"loading": "Cargando...",
"saving": "Guardando...",
"saved": "Guardado",
"error": "Error",
"success": "Éxito",
"warning": "Advertencia",
"info": "Información",
"processing": "Procesando...",
"completed": "Completado",
"failed": "Fallido",
"cancelled": "Cancelado",
"pending": "Pendiente",
"ready": "Listo"
},
"language": {
"current": "Idioma",
"select": "Seleccionar idioma",
"select_help": "Elige tu idioma preferido para la interfaz",
"english": "Inglés",
"chinese_simplified": "Chino (simplificado)",
"chinese_traditional": "Chino (tradicional)",
"russian": "Ruso",
"german": "Alemán",
"japanese": "Japonés",
"korean": "Coreano",
"french": "Francés",
"spanish": "Español"
}
},
"header": {
"appTitle": "Gestor LoRA",
"navigation": {
"loras": "LoRAs",
"recipes": "Recetas",
"checkpoints": "Checkpoints",
"embeddings": "Embeddings",
"statistics": "Estadísticas"
},
"search": {
"placeholder": "Buscar...",
"placeholders": {
"loras": "Buscar LoRAs...",
"recipes": "Buscar recetas...",
"checkpoints": "Buscar checkpoints...",
"embeddings": "Buscar embeddings..."
},
"options": "Opciones de búsqueda",
"searchIn": "Buscar en:",
"notAvailable": "Búsqueda no disponible en la página de estadísticas",
"filters": {
"filename": "Nombre de archivo",
"modelname": "Nombre del modelo",
"tags": "Etiquetas",
"creator": "Creador",
"title": "Título de la receta",
"loraName": "Nombre del archivo LoRA",
"loraModel": "Nombre del modelo LoRA"
}
},
"filter": {
"title": "Filtrar modelos",
"baseModel": "Modelo base",
"modelTags": "Etiquetas (Top 20)",
"clearAll": "Limpiar todos los filtros"
},
"theme": {
"toggle": "Cambiar tema",
"switchToLight": "Cambiar a tema claro",
"switchToDark": "Cambiar a tema oscuro",
"switchToAuto": "Cambiar a tema automático"
}
},
"loras": {
"title": "Modelos LoRA",
"controls": {
"sort": {
"title": "Ordenar modelos por...",
"name": "Nombre",
"nameAsc": "A - Z",
"nameDesc": "Z - A",
"date": "Fecha de adición",
"dateDesc": "Más reciente",
"dateAsc": "Más antiguo",
"size": "Tamaño de archivo",
"sizeDesc": "Más grande",
"sizeAsc": "Más pequeño"
},
"refresh": {
"title": "Actualizar lista de modelos",
"quick": "Actualización rápida (incremental)",
"full": "Reconstrucción completa (completa)"
},
"fetch": "Obtener de Civitai",
"download": "Descargar desde URL",
"bulk": "Operaciones masivas",
"duplicates": "Encontrar duplicados",
"favorites": "Mostrar solo favoritos"
},
"bulkOperations": {
"title": "Operaciones masivas",
"selected": "{count} seleccionado(s)",
"sendToWorkflow": "Enviar todos los LoRAs seleccionados al flujo de trabajo",
"copyAll": "Copiar sintaxis de todos los LoRAs seleccionados",
"refreshAll": "Actualizar metadatos de CivitAI para modelos seleccionados",
"moveAll": "Mover modelos seleccionados a carpeta",
"deleteAll": "Eliminar modelos seleccionados",
"clear": "Limpiar selección"
},
"contextMenu": {
"refreshMetadata": "Actualizar datos de Civitai",
"relinkCivitai": "Volver a vincular con Civitai",
"copySyntax": "Copiar sintaxis LoRA",
"copyFilename": "Copiar nombre de archivo del modelo",
"copyRecipeSyntax": "Copiar sintaxis de receta",
"sendToWorkflowAppend": "Enviar al flujo de trabajo (agregar)",
"sendToWorkflowReplace": "Enviar al flujo de trabajo (reemplazar)",
"openExamplesFolder": "Abrir carpeta de ejemplos",
"downloadExamples": "Descargar imágenes de ejemplo",
"replacePreview": "Reemplazar vista previa",
"setContentRating": "Establecer clasificación de contenido",
"moveToFolder": "Mover a carpeta",
"excludeModel": "Excluir modelo",
"deleteModel": "Eliminar modelo",
"shareRecipe": "Compartir receta",
"viewAllLoras": "Ver todos los LoRAs",
"downloadMissingLoras": "Descargar LoRAs faltantes",
"deleteRecipe": "Eliminar receta"
},
"modal": {
"title": "Detalles LoRA",
"tabs": {
"examples": "Ejemplos",
"description": "Descripción del modelo",
"recipes": "Recetas"
},
"info": {
"filename": "Nombre de archivo",
"modelName": "Nombre del modelo",
"baseModel": "Modelo base",
"fileSize": "Tamaño de archivo",
"dateAdded": "Fecha de adición",
"triggerWords": "Palabras clave",
"description": "Descripción",
"tags": "Etiquetas",
"rating": "Calificación",
"downloads": "Descargas",
"likes": "Me gusta",
"version": "Versión"
},
"actions": {
"copyTriggerWords": "Copiar palabras clave",
"copyLoraName": "Copiar nombre LoRA",
"sendToWorkflow": "Enviar al flujo de trabajo",
"viewOnCivitai": "Ver en Civitai",
"downloadExamples": "Descargar imágenes de ejemplo"
}
}
},
"recipes": {
"title": "Recetas LoRA",
"controls": {
"import": "Importar receta",
"refresh": {
"title": "Actualizar lista de recetas"
},
"duplicates": {
"title": "Encontrar recetas duplicadas"
},
"filteredByLora": "Filtrado por LoRA",
"create": "Crear receta",
"export": "Exportar seleccionados",
"downloadMissing": "Descargar LoRAs faltantes"
},
"duplicates": {
"found": "Se encontraron {count} grupos duplicados",
"keepLatest": "Mantener últimas versiones",
"deleteSelected": "Eliminar seleccionados"
},
"card": {
"author": "Autor",
"loras": "{count} LoRAs",
"tags": "Etiquetas",
"actions": {
"sendToWorkflow": "Enviar al flujo de trabajo",
"edit": "Editar receta",
"duplicate": "Duplicar receta",
"export": "Exportar receta",
"delete": "Eliminar receta"
}
}
},
"checkpoints": {
"title": "Modelos Checkpoint",
"info": {
"filename": "Nombre de archivo",
"modelName": "Nombre del modelo",
"baseModel": "Modelo base",
"fileSize": "Tamaño de archivo",
"dateAdded": "Fecha de adición"
}
},
"embeddings": {
"title": "Modelos Embedding",
"info": {
"filename": "Nombre de archivo",
"modelName": "Nombre del modelo",
"triggerWords": "Palabras clave",
"fileSize": "Tamaño de archivo",
"dateAdded": "Fecha de adición"
}
},
"sidebar": {
"modelRoot": "Raíz de modelos",
"collapseAll": "Contraer todas las carpetas",
"pinToggle": "Fijar/Desfijar barra lateral"
},
"statistics": {
"title": "Estadísticas",
"tabs": {
"overview": "Resumen",
"usage": "Análisis de uso",
"collection": "Colección",
"storage": "Almacenamiento",
"insights": "Perspectivas"
},
"overview": {
"title": "Resumen",
"totalLoras": "Total LoRAs",
"totalCheckpoints": "Total Checkpoints",
"totalEmbeddings": "Total Embeddings",
"totalSize": "Tamaño total",
"favoriteModels": "Modelos favoritos"
},
"charts": {
"modelsByType": "Modelos por tipo",
"modelsByBaseModel": "Modelos por modelo base",
"modelsBySize": "Modelos por tamaño de archivo",
"modelsAddedOverTime": "Modelos agregados a lo largo del tiempo"
}
},
"modals": {
"delete": {
"title": "Confirmar eliminación",
"message": "¿Estás seguro de que quieres eliminar este modelo?",
"warningMessage": "Esta acción no se puede deshacer.",
"confirm": "Eliminar",
"cancel": "Cancelar"
},
"exclude": {
"title": "Excluir modelo",
"message": "¿Estás seguro de que quieres excluir este modelo de la biblioteca?",
"confirm": "Excluir",
"cancel": "Cancelar"
},
"download": {
"title": "Descargar modelo desde URL",
"url": "URL de Civitai",
"placeholder": "https://civitai.com/models/...",
"locationPreview": "Vista previa de ubicación de descarga",
"useDefaultPath": "Usar ruta predeterminada",
"useDefaultPathTooltip": "Cuando está habilitado, los archivos se organizan automáticamente usando plantillas de ruta configuradas",
"selectRootDirectory": "Seleccionar directorio raíz",
"download": "Descargar",
"cancel": "Cancelar"
},
"move": {
"title": "Mover modelos",
"selectFolder": "Seleccionar carpeta de destino",
"createFolder": "Crear nueva carpeta",
"folderName": "Nombre de carpeta",
"move": "Mover",
"cancel": "Cancelar"
},
"contentRating": {
"title": "Establecer clasificación de contenido",
"current": "Actual",
"levels": {
"pg": "Para todos los públicos",
"pg13": "13 años y más",
"r": "Restringido",
"x": "Solo adultos",
"xxx": "Explícito"
}
}
},
"errors": {
"general": "Ocurrió un error",
"networkError": "Error de red. Por favor verifica tu conexión.",
"serverError": "Error del servidor. Por favor intenta de nuevo más tarde.",
"fileNotFound": "Archivo no encontrado",
"invalidFile": "Formato de archivo inválido",
"uploadFailed": "Subida fallida",
"downloadFailed": "Descarga fallida",
"saveFailed": "Guardado fallido",
"loadFailed": "Carga fallida",
"deleteFailed": "Eliminación fallida",
"moveFailed": "Movimiento fallido",
"copyFailed": "Copia fallida",
"fetchFailed": "Falló la obtención de datos de Civitai",
"invalidUrl": "Formato de URL inválido",
"missingPermissions": "Permisos insuficientes"
},
"success": {
"saved": "Guardado exitosamente",
"deleted": "Eliminado exitosamente",
"moved": "Movido exitosamente",
"copied": "Copiado exitosamente",
"downloaded": "Descargado exitosamente",
"uploaded": "Subido exitosamente",
"refreshed": "Actualizado exitosamente",
"exported": "Exportado exitosamente",
"imported": "Importado exitosamente"
},
"keyboard": {
"navigation": "Navegación por teclado:",
"shortcuts": {
"pageUp": "Desplazar una página hacia arriba",
"pageDown": "Desplazar una página hacia abajo",
"home": "Ir al inicio",
"end": "Ir al final",
"bulkMode": "Alternar modo masivo",
"search": "Enfocar búsqueda",
"escape": "Cerrar modal/panel"
}
},
"initialization": {
"title": "Inicializando",
"message": "Preparando tu espacio de trabajo...",
"status": "Inicializando...",
"estimatingTime": "Estimando tiempo...",
"loras": {
"title": "Inicializando Gestor LoRA",
"message": "Escaneando y construyendo caché LoRA. Esto puede tomar unos minutos..."
},
"checkpoints": {
"title": "Inicializando Gestor de Checkpoint",
"message": "Escaneando y construyendo caché de checkpoint. Esto puede tomar unos minutos..."
},
"embeddings": {
"title": "Inicializando Gestor de Embedding",
"message": "Escaneando y construyendo caché de embedding. Esto puede tomar unos minutos..."
},
"recipes": {
"title": "Inicializando Gestor de Recetas",
"message": "Cargando y procesando recetas. Esto puede tomar unos minutos..."
},
"statistics": {
"title": "Inicializando Estadísticas",
"message": "Procesando datos de modelo para estadísticas. Esto puede tomar unos minutos..."
},
"tips": {
"title": "Consejos y trucos",
"civitai": {
"title": "Integración con Civitai",
"description": "Conecta tu cuenta de Civitai: Visita Avatar de perfil → Configuración → Claves API → Agregar clave API, luego pégala en la configuración de Lora Manager.",
"alt": "Configuración API de Civitai"
},
"download": {
"title": "Descarga fácil",
"description": "Usa URLs de Civitai para descargar e instalar rápidamente nuevos modelos.",
"alt": "Descarga de Civitai"
},
"recipes": {
"title": "Guardar recetas",
"description": "Crea recetas para guardar tus combinaciones de modelos favoritas para uso futuro.",
"alt": "Recetas"
},
"filter": {
"title": "Filtrado rápido",
"description": "Filtra modelos por etiquetas o tipo de modelo base usando el botón de filtro en el encabezado.",
"alt": "Filtrar modelos"
},
"search": {
"title": "Búsqueda rápida",
"description": "Presiona Ctrl+F (Cmd+F en Mac) para buscar rápidamente dentro de tu vista actual.",
"alt": "Búsqueda rápida"
}
},
"steps": {
"scanning": "Escaneando archivos de modelo...",
"processing": "Procesando metadatos...",
"building": "Construyendo caché...",
"finalizing": "Finalizando..."
}
},
"duplicates": {
"found": "Se encontraron {count} grupos duplicados",
"showNotification": "Mostrar notificación de duplicados",
"deleteSelected": "Eliminar seleccionados",
"exitMode": "Salir del modo",
"help": {
"identicalHashes": "Hashes idénticos significan archivos de modelo idénticos, aunque tengan nombres o vistas previas diferentes.",
"keepOne": "Mantén solo una versión (preferiblemente con mejores metadatos/vistas previas) y elimina las otras de forma segura."
}
},
"tooltips": {
"refresh": "Actualizar la lista de modelos",
"bulkOperations": "Seleccionar múltiples modelos para operaciones por lotes",
"favorites": "Mostrar solo modelos favoritos",
"duplicates": "Encontrar y gestionar modelos duplicados",
"search": "Buscar modelos por nombre, etiquetas u otros criterios",
"filter": "Filtrar modelos por varios criterios",
"sort": "Ordenar modelos por diferentes atributos",
"backToTop": "Volver al inicio de la página"
}
}

453
locales/fr.json Normal file
View File

@@ -0,0 +1,453 @@
{
"common": {
"file": "Fichier",
"folder": "Dossier",
"name": "Nom",
"size": "Taille",
"date": "Date",
"type": "Type",
"path": "Chemin",
"fileSize": {
"zero": "0 Octets",
"bytes": "Octets",
"kb": "Ko",
"mb": "Mo",
"gb": "Go",
"tb": "To"
},
"actions": {
"save": "Enregistrer",
"cancel": "Annuler",
"delete": "Supprimer",
"edit": "Modifier",
"copy": "Copier",
"move": "Déplacer",
"refresh": "Actualiser",
"download": "Télécharger",
"upload": "Téléverser",
"search": "Rechercher",
"filter": "Filtrer",
"sort": "Trier",
"select": "Sélectionner",
"selectAll": "Tout sélectionner",
"deselectAll": "Tout désélectionner",
"confirm": "Confirmer",
"close": "Fermer",
"back": "Retour",
"next": "Suivant",
"previous": "Précédent",
"view": "Voir",
"preview": "Aperçu",
"details": "Détails",
"backToTop": "Retour en haut",
"settings": "Paramètres",
"help": "Aide",
"about": "À propos"
},
"status": {
"loading": "Chargement...",
"saving": "Enregistrement...",
"saved": "Enregistré",
"error": "Erreur",
"success": "Succès",
"warning": "Avertissement",
"info": "Information",
"processing": "Traitement...",
"completed": "Terminé",
"failed": "Échec",
"cancelled": "Annulé",
"pending": "En attente",
"ready": "Prêt"
},
"language": {
"current": "Langue",
"select": "Sélectionner la langue",
"select_help": "Choisissez votre langue préférée pour l'interface",
"english": "Anglais",
"chinese_simplified": "Chinois (simplifié)",
"chinese_traditional": "Chinois (traditionnel)",
"russian": "Russe",
"german": "Allemand",
"japanese": "Japonais",
"korean": "Coréen",
"french": "Français",
"spanish": "Espagnol"
}
},
"header": {
"appTitle": "Gestionnaire LoRA",
"navigation": {
"loras": "LoRAs",
"recipes": "Recettes",
"checkpoints": "Checkpoints",
"embeddings": "Embeddings",
"statistics": "Statistiques"
},
"search": {
"placeholder": "Rechercher...",
"placeholders": {
"loras": "Rechercher des LoRAs...",
"recipes": "Rechercher des recettes...",
"checkpoints": "Rechercher des checkpoints...",
"embeddings": "Rechercher des embeddings..."
},
"options": "Options de recherche",
"searchIn": "Rechercher dans :",
"notAvailable": "Recherche non disponible sur la page statistiques",
"filters": {
"filename": "Nom de fichier",
"modelname": "Nom du modèle",
"tags": "Tags",
"creator": "Créateur",
"title": "Titre de la recette",
"loraName": "Nom du fichier LoRA",
"loraModel": "Nom du modèle LoRA"
}
},
"filter": {
"title": "Filtrer les modèles",
"baseModel": "Modèle de base",
"modelTags": "Tags (Top 20)",
"clearAll": "Effacer tous les filtres"
},
"theme": {
"toggle": "Basculer le thème",
"switchToLight": "Passer au thème clair",
"switchToDark": "Passer au thème sombre",
"switchToAuto": "Passer au thème automatique"
}
},
"loras": {
"title": "Modèles LoRA",
"controls": {
"sort": {
"title": "Trier les modèles par...",
"name": "Nom",
"nameAsc": "A - Z",
"nameDesc": "Z - A",
"date": "Date d'ajout",
"dateDesc": "Plus récent",
"dateAsc": "Plus ancien",
"size": "Taille du fichier",
"sizeDesc": "Plus grand",
"sizeAsc": "Plus petit"
},
"refresh": {
"title": "Actualiser la liste des modèles",
"quick": "Actualisation rapide (incrémentielle)",
"full": "Reconstruction complète (complète)"
},
"fetch": "Récupérer depuis Civitai",
"download": "Télécharger depuis l'URL",
"bulk": "Opérations en lot",
"duplicates": "Trouver les doublons",
"favorites": "Afficher uniquement les favoris"
},
"bulkOperations": {
"title": "Opérations en lot",
"selected": "{count} sélectionné(s)",
"sendToWorkflow": "Envoyer tous les LoRAs sélectionnés au workflow",
"copyAll": "Copier la syntaxe de tous les LoRAs sélectionnés",
"refreshAll": "Actualiser les métadonnées CivitAI pour les modèles sélectionnés",
"moveAll": "Déplacer les modèles sélectionnés vers un dossier",
"deleteAll": "Supprimer les modèles sélectionnés",
"clear": "Effacer la sélection"
},
"contextMenu": {
"refreshMetadata": "Actualiser les données Civitai",
"relinkCivitai": "Relier à nouveau à Civitai",
"copySyntax": "Copier la syntaxe LoRA",
"copyFilename": "Copier le nom de fichier du modèle",
"copyRecipeSyntax": "Copier la syntaxe de la recette",
"sendToWorkflowAppend": "Envoyer au workflow (ajouter)",
"sendToWorkflowReplace": "Envoyer au workflow (remplacer)",
"openExamplesFolder": "Ouvrir le dossier d'exemples",
"downloadExamples": "Télécharger les images d'exemple",
"replacePreview": "Remplacer l'aperçu",
"setContentRating": "Définir la classification du contenu",
"moveToFolder": "Déplacer vers le dossier",
"excludeModel": "Exclure le modèle",
"deleteModel": "Supprimer le modèle",
"shareRecipe": "Partager la recette",
"viewAllLoras": "Voir tous les LoRAs",
"downloadMissingLoras": "Télécharger les LoRAs manquants",
"deleteRecipe": "Supprimer la recette"
},
"modal": {
"title": "Détails LoRA",
"tabs": {
"examples": "Exemples",
"description": "Description du modèle",
"recipes": "Recettes"
},
"info": {
"filename": "Nom de fichier",
"modelName": "Nom du modèle",
"baseModel": "Modèle de base",
"fileSize": "Taille du fichier",
"dateAdded": "Date d'ajout",
"triggerWords": "Mots déclencheurs",
"description": "Description",
"tags": "Tags",
"rating": "Évaluation",
"downloads": "Téléchargements",
"likes": "J'aime",
"version": "Version"
},
"actions": {
"copyTriggerWords": "Copier les mots déclencheurs",
"copyLoraName": "Copier le nom LoRA",
"sendToWorkflow": "Envoyer au workflow",
"viewOnCivitai": "Voir sur Civitai",
"downloadExamples": "Télécharger les images d'exemple"
}
}
},
"recipes": {
"title": "Recettes LoRA",
"controls": {
"import": "Importer une recette",
"refresh": {
"title": "Actualiser la liste des recettes"
},
"duplicates": {
"title": "Trouver les recettes en double"
},
"filteredByLora": "Filtré par LoRA",
"create": "Créer une recette",
"export": "Exporter la sélection",
"downloadMissing": "Télécharger les LoRAs manquants"
},
"duplicates": {
"found": "{count} groupes de doublons trouvés",
"keepLatest": "Garder les dernières versions",
"deleteSelected": "Supprimer la sélection"
},
"card": {
"author": "Auteur",
"loras": "{count} LoRAs",
"tags": "Tags",
"actions": {
"sendToWorkflow": "Envoyer au workflow",
"edit": "Modifier la recette",
"duplicate": "Dupliquer la recette",
"export": "Exporter la recette",
"delete": "Supprimer la recette"
}
}
},
"checkpoints": {
"title": "Modèles Checkpoint",
"info": {
"filename": "Nom de fichier",
"modelName": "Nom du modèle",
"baseModel": "Modèle de base",
"fileSize": "Taille du fichier",
"dateAdded": "Date d'ajout"
}
},
"embeddings": {
"title": "Modèles Embedding",
"info": {
"filename": "Nom de fichier",
"modelName": "Nom du modèle",
"triggerWords": "Mots déclencheurs",
"fileSize": "Taille du fichier",
"dateAdded": "Date d'ajout"
}
},
"sidebar": {
"modelRoot": "Racine des modèles",
"collapseAll": "Replier tous les dossiers",
"pinToggle": "Épingler/Désépingler la barre latérale"
},
"statistics": {
"title": "Statistiques",
"tabs": {
"overview": "Aperçu",
"usage": "Analyse d'utilisation",
"collection": "Collection",
"storage": "Stockage",
"insights": "Analyses"
},
"overview": {
"title": "Aperçu",
"totalLoras": "Total LoRAs",
"totalCheckpoints": "Total Checkpoints",
"totalEmbeddings": "Total Embeddings",
"totalSize": "Taille totale",
"favoriteModels": "Modèles favoris"
},
"charts": {
"modelsByType": "Modèles par type",
"modelsByBaseModel": "Modèles par modèle de base",
"modelsBySize": "Modèles par taille de fichier",
"modelsAddedOverTime": "Modèles ajoutés au fil du temps"
}
},
"modals": {
"delete": {
"title": "Confirmer la suppression",
"message": "Êtes-vous sûr de vouloir supprimer ce modèle ?",
"warningMessage": "Cette action ne peut pas être annulée.",
"confirm": "Supprimer",
"cancel": "Annuler"
},
"exclude": {
"title": "Exclure le modèle",
"message": "Êtes-vous sûr de vouloir exclure ce modèle de la bibliothèque ?",
"confirm": "Exclure",
"cancel": "Annuler"
},
"download": {
"title": "Télécharger le modèle depuis l'URL",
"url": "URL Civitai",
"placeholder": "https://civitai.com/models/...",
"locationPreview": "Aperçu de l'emplacement de téléchargement",
"useDefaultPath": "Utiliser le chemin par défaut",
"useDefaultPathTooltip": "Quand activé, les fichiers sont automatiquement organisés en utilisant les modèles de chemin configurés",
"selectRootDirectory": "Sélectionner un répertoire racine",
"download": "Télécharger",
"cancel": "Annuler"
},
"move": {
"title": "Déplacer les modèles",
"selectFolder": "Sélectionner le dossier de destination",
"createFolder": "Créer un nouveau dossier",
"folderName": "Nom du dossier",
"move": "Déplacer",
"cancel": "Annuler"
},
"contentRating": {
"title": "Définir la classification du contenu",
"current": "Actuel",
"levels": {
"pg": "Tout public",
"pg13": "13 ans et plus",
"r": "Restreint",
"x": "Adultes seulement",
"xxx": "Explicite"
}
}
},
"errors": {
"general": "Une erreur s'est produite",
"networkError": "Erreur réseau. Veuillez vérifier votre connexion.",
"serverError": "Erreur serveur. Veuillez réessayer plus tard.",
"fileNotFound": "Fichier non trouvé",
"invalidFile": "Format de fichier invalide",
"uploadFailed": "Échec du téléversement",
"downloadFailed": "Échec du téléchargement",
"saveFailed": "Échec de l'enregistrement",
"loadFailed": "Échec du chargement",
"deleteFailed": "Échec de la suppression",
"moveFailed": "Échec du déplacement",
"copyFailed": "Échec de la copie",
"fetchFailed": "Échec de récupération des données depuis Civitai",
"invalidUrl": "Format d'URL invalide",
"missingPermissions": "Permissions insuffisantes"
},
"success": {
"saved": "Enregistré avec succès",
"deleted": "Supprimé avec succès",
"moved": "Déplacé avec succès",
"copied": "Copié avec succès",
"downloaded": "Téléchargé avec succès",
"uploaded": "Téléversé avec succès",
"refreshed": "Actualisé avec succès",
"exported": "Exporté avec succès",
"imported": "Importé avec succès"
},
"keyboard": {
"navigation": "Navigation au clavier :",
"shortcuts": {
"pageUp": "Faire défiler d'une page vers le haut",
"pageDown": "Faire défiler d'une page vers le bas",
"home": "Aller en haut",
"end": "Aller en bas",
"bulkMode": "Basculer le mode lot",
"search": "Focuser la recherche",
"escape": "Fermer modal/panneau"
}
},
"initialization": {
"title": "Initialisation",
"message": "Préparation de votre espace de travail...",
"status": "Initialisation...",
"estimatingTime": "Estimation du temps...",
"loras": {
"title": "Initialisation du gestionnaire LoRA",
"message": "Analyse et construction du cache LoRA. Cela peut prendre quelques minutes..."
},
"checkpoints": {
"title": "Initialisation du gestionnaire Checkpoint",
"message": "Analyse et construction du cache checkpoint. Cela peut prendre quelques minutes..."
},
"embeddings": {
"title": "Initialisation du gestionnaire Embedding",
"message": "Analyse et construction du cache embedding. Cela peut prendre quelques minutes..."
},
"recipes": {
"title": "Initialisation du gestionnaire de recettes",
"message": "Chargement et traitement des recettes. Cela peut prendre quelques minutes..."
},
"statistics": {
"title": "Initialisation des statistiques",
"message": "Traitement des données de modèle pour les statistiques. Cela peut prendre quelques minutes..."
},
"tips": {
"title": "Conseils et astuces",
"civitai": {
"title": "Intégration Civitai",
"description": "Connectez votre compte Civitai : Visitez Avatar de profil → Paramètres → Clés API → Ajouter une clé API, puis collez-la dans les paramètres de Lora Manager.",
"alt": "Configuration API Civitai"
},
"download": {
"title": "Téléchargement facile",
"description": "Utilisez les URLs Civitai pour télécharger et installer rapidement de nouveaux modèles.",
"alt": "Téléchargement Civitai"
},
"recipes": {
"title": "Sauvegarder les recettes",
"description": "Créez des recettes pour sauvegarder vos combinaisons de modèles préférées pour une utilisation future.",
"alt": "Recettes"
},
"filter": {
"title": "Filtrage rapide",
"description": "Filtrez les modèles par tags ou type de modèle de base en utilisant le bouton filtre dans l'en-tête.",
"alt": "Filtrer les modèles"
},
"search": {
"title": "Recherche rapide",
"description": "Appuyez sur Ctrl+F (Cmd+F sur Mac) pour rechercher rapidement dans votre vue actuelle.",
"alt": "Recherche rapide"
}
},
"steps": {
"scanning": "Analyse des fichiers de modèle...",
"processing": "Traitement des métadonnées...",
"building": "Construction du cache...",
"finalizing": "Finalisation..."
}
},
"duplicates": {
"found": "{count} groupes de doublons trouvés",
"showNotification": "Afficher la notification des doublons",
"deleteSelected": "Supprimer la sélection",
"exitMode": "Quitter le mode",
"help": {
"identicalHashes": "Des hachages identiques signifient des fichiers de modèle identiques, même s'ils ont des noms ou des aperçus différents.",
"keepOne": "Gardez seulement une version (de préférence avec de meilleures métadonnées/aperçus) et supprimez les autres en toute sécurité."
}
},
"tooltips": {
"refresh": "Actualiser la liste des modèles",
"bulkOperations": "Sélectionner plusieurs modèles pour les opérations par lot",
"favorites": "Afficher uniquement les modèles favoris",
"duplicates": "Trouver et gérer les modèles en double",
"search": "Rechercher des modèles par nom, tags ou autres critères",
"filter": "Filtrer les modèles selon divers critères",
"sort": "Trier les modèles selon différents attributs",
"backToTop": "Remonter en haut de la page"
}
}

453
locales/ja.json Normal file
View File

@@ -0,0 +1,453 @@
{
"common": {
"file": "ファイル",
"folder": "フォルダ",
"name": "名前",
"size": "サイズ",
"date": "日付",
"type": "種類",
"path": "パス",
"fileSize": {
"zero": "0 バイト",
"bytes": "バイト",
"kb": "KB",
"mb": "MB",
"gb": "GB",
"tb": "TB"
},
"actions": {
"save": "保存",
"cancel": "キャンセル",
"delete": "削除",
"edit": "編集",
"copy": "コピー",
"move": "移動",
"refresh": "更新",
"download": "ダウンロード",
"upload": "アップロード",
"search": "検索",
"filter": "フィルター",
"sort": "ソート",
"select": "選択",
"selectAll": "すべて選択",
"deselectAll": "選択解除",
"confirm": "確認",
"close": "閉じる",
"back": "戻る",
"next": "次へ",
"previous": "前へ",
"view": "表示",
"preview": "プレビュー",
"details": "詳細",
"backToTop": "トップに戻る",
"settings": "設定",
"help": "ヘルプ",
"about": "について"
},
"status": {
"loading": "読み込み中...",
"saving": "保存中...",
"saved": "保存済み",
"error": "エラー",
"success": "成功",
"warning": "警告",
"info": "情報",
"processing": "処理中...",
"completed": "完了",
"failed": "失敗",
"cancelled": "キャンセル",
"pending": "待機中",
"ready": "準備完了"
},
"language": {
"current": "言語",
"select": "言語を選択",
"select_help": "インターフェース言語を選択してください",
"english": "英語",
"chinese_simplified": "中国語(簡体字)",
"chinese_traditional": "中国語(繁体字)",
"russian": "ロシア語",
"german": "ドイツ語",
"japanese": "日本語",
"korean": "韓国語",
"french": "フランス語",
"spanish": "スペイン語"
}
},
"header": {
"appTitle": "LoRA マネージャー",
"navigation": {
"loras": "LoRA",
"recipes": "レシピ",
"checkpoints": "チェックポイント",
"embeddings": "エンベディング",
"statistics": "統計"
},
"search": {
"placeholder": "検索...",
"placeholders": {
"loras": "LoRAを検索...",
"recipes": "レシピを検索...",
"checkpoints": "チェックポイントを検索...",
"embeddings": "エンベディングを検索..."
},
"options": "検索オプション",
"searchIn": "検索対象:",
"notAvailable": "統計ページでは検索は利用できません",
"filters": {
"filename": "ファイル名",
"modelname": "モデル名",
"tags": "タグ",
"creator": "作成者",
"title": "レシピタイトル",
"loraName": "LoRAファイル名",
"loraModel": "LoRAモデル名"
}
},
"filter": {
"title": "モデルをフィルター",
"baseModel": "ベースモデル",
"modelTags": "タグトップ20",
"clearAll": "すべてのフィルターをクリア"
},
"theme": {
"toggle": "テーマ切り替え",
"switchToLight": "ライトテーマに切り替え",
"switchToDark": "ダークテーマに切り替え",
"switchToAuto": "オートテーマに切り替え"
}
},
"loras": {
"title": "LoRAモデル",
"controls": {
"sort": {
"title": "モデルをソート...",
"name": "名前",
"nameAsc": "A - Z",
"nameDesc": "Z - A",
"date": "追加日",
"dateDesc": "新しい順",
"dateAsc": "古い順",
"size": "ファイルサイズ",
"sizeDesc": "大きい順",
"sizeAsc": "小さい順"
},
"refresh": {
"title": "モデルリストを更新",
"quick": "クイック更新(増分)",
"full": "完全再構築(完全)"
},
"fetch": "Civitaiから取得",
"download": "URLからダウンロード",
"bulk": "一括操作",
"duplicates": "重複を検索",
"favorites": "お気に入りのみ表示"
},
"bulkOperations": {
"title": "一括操作",
"selected": "{count}個選択中",
"sendToWorkflow": "選択したLoRAをワークフローに送信",
"copyAll": "選択したLoRA構文をコピー",
"refreshAll": "選択したモデルのCivitAIメタデータを更新",
"moveAll": "選択したモデルをフォルダに移動",
"deleteAll": "選択したモデルを削除",
"clear": "選択をクリア"
},
"contextMenu": {
"refreshMetadata": "Civitaiデータを更新",
"relinkCivitai": "Civitaiに再リンク",
"copySyntax": "LoRA構文をコピー",
"copyFilename": "モデルファイル名をコピー",
"copyRecipeSyntax": "レシピ構文をコピー",
"sendToWorkflowAppend": "ワークフローに送信(追加)",
"sendToWorkflowReplace": "ワークフローに送信(置換)",
"openExamplesFolder": "サンプルフォルダを開く",
"downloadExamples": "サンプル画像をダウンロード",
"replacePreview": "プレビューを置換",
"setContentRating": "コンテンツレーティングを設定",
"moveToFolder": "フォルダに移動",
"excludeModel": "モデルを除外",
"deleteModel": "モデルを削除",
"shareRecipe": "レシピを共有",
"viewAllLoras": "すべてのLoRAを表示",
"downloadMissingLoras": "不足しているLoRAをダウンロード",
"deleteRecipe": "レシピを削除"
},
"modal": {
"title": "LoRA詳細",
"tabs": {
"examples": "サンプル",
"description": "モデル説明",
"recipes": "レシピ"
},
"info": {
"filename": "ファイル名",
"modelName": "モデル名",
"baseModel": "ベースモデル",
"fileSize": "ファイルサイズ",
"dateAdded": "追加日",
"triggerWords": "トリガーワード",
"description": "説明",
"tags": "タグ",
"rating": "評価",
"downloads": "ダウンロード数",
"likes": "いいね数",
"version": "バージョン"
},
"actions": {
"copyTriggerWords": "トリガーワードをコピー",
"copyLoraName": "LoRA名をコピー",
"sendToWorkflow": "ワークフローに送信",
"viewOnCivitai": "Civitaiで表示",
"downloadExamples": "サンプル画像をダウンロード"
}
}
},
"recipes": {
"title": "LoRAレシピ",
"controls": {
"import": "レシピをインポート",
"refresh": {
"title": "レシピリストを更新"
},
"duplicates": {
"title": "重複レシピを検索"
},
"filteredByLora": "LoRAでフィルタ",
"create": "レシピを作成",
"export": "選択項目をエクスポート",
"downloadMissing": "不足しているLoRAをダウンロード"
},
"duplicates": {
"found": "{count}個の重複グループが見つかりました",
"keepLatest": "最新バージョンを保持",
"deleteSelected": "選択項目を削除"
},
"card": {
"author": "作者",
"loras": "{count}個のLoRA",
"tags": "タグ",
"actions": {
"sendToWorkflow": "ワークフローに送信",
"edit": "レシピを編集",
"duplicate": "レシピを複製",
"export": "レシピをエクスポート",
"delete": "レシピを削除"
}
}
},
"checkpoints": {
"title": "チェックポイントモデル",
"info": {
"filename": "ファイル名",
"modelName": "モデル名",
"baseModel": "ベースモデル",
"fileSize": "ファイルサイズ",
"dateAdded": "追加日"
}
},
"embeddings": {
"title": "エンベディングモデル",
"info": {
"filename": "ファイル名",
"modelName": "モデル名",
"triggerWords": "トリガーワード",
"fileSize": "ファイルサイズ",
"dateAdded": "追加日"
}
},
"sidebar": {
"modelRoot": "モデルルート",
"collapseAll": "すべてのフォルダを折りたたむ",
"pinToggle": "サイドバーをピン留め/解除"
},
"statistics": {
"title": "統計",
"tabs": {
"overview": "概要",
"usage": "使用分析",
"collection": "コレクション",
"storage": "ストレージ",
"insights": "インサイト"
},
"overview": {
"title": "概要",
"totalLoras": "LoRA総数",
"totalCheckpoints": "チェックポイント総数",
"totalEmbeddings": "エンベディング総数",
"totalSize": "総サイズ",
"favoriteModels": "お気に入りモデル"
},
"charts": {
"modelsByType": "タイプ別モデル",
"modelsByBaseModel": "ベースモデル別",
"modelsBySize": "ファイルサイズ別",
"modelsAddedOverTime": "時系列追加モデル"
}
},
"modals": {
"delete": {
"title": "削除の確認",
"message": "このモデルを削除してもよろしいですか?",
"warningMessage": "この操作は元に戻せません。",
"confirm": "削除",
"cancel": "キャンセル"
},
"exclude": {
"title": "モデルを除外",
"message": "このモデルをライブラリから除外してもよろしいですか?",
"confirm": "除外",
"cancel": "キャンセル"
},
"download": {
"title": "URLからモデルをダウンロード",
"url": "Civitai URL",
"placeholder": "https://civitai.com/models/...",
"locationPreview": "ダウンロード場所プレビュー",
"useDefaultPath": "デフォルトパスを使用",
"useDefaultPathTooltip": "有効にすると、設定されたパステンプレートを使用してファイルが自動的に整理されます",
"selectRootDirectory": "ルートディレクトリを選択",
"download": "ダウンロード",
"cancel": "キャンセル"
},
"move": {
"title": "モデルを移動",
"selectFolder": "移動先フォルダを選択",
"createFolder": "新しいフォルダを作成",
"folderName": "フォルダ名",
"move": "移動",
"cancel": "キャンセル"
},
"contentRating": {
"title": "コンテンツレーティングを設定",
"current": "現在",
"levels": {
"pg": "全年齢",
"pg13": "13歳以上",
"r": "制限あり",
"x": "成人向け",
"xxx": "露骨"
}
}
},
"errors": {
"general": "エラーが発生しました",
"networkError": "ネットワークエラー。接続を確認してください。",
"serverError": "サーバーエラー。後でもう一度試してください。",
"fileNotFound": "ファイルが見つかりません",
"invalidFile": "無効なファイル形式",
"uploadFailed": "アップロードに失敗しました",
"downloadFailed": "ダウンロードに失敗しました",
"saveFailed": "保存に失敗しました",
"loadFailed": "読み込みに失敗しました",
"deleteFailed": "削除に失敗しました",
"moveFailed": "移動に失敗しました",
"copyFailed": "コピーに失敗しました",
"fetchFailed": "Civitaiからデータを取得できませんでした",
"invalidUrl": "無効なURL形式",
"missingPermissions": "権限が不足しています"
},
"success": {
"saved": "正常に保存されました",
"deleted": "正常に削除されました",
"moved": "正常に移動されました",
"copied": "正常にコピーされました",
"downloaded": "正常にダウンロードされました",
"uploaded": "正常にアップロードされました",
"refreshed": "正常に更新されました",
"exported": "正常にエクスポートされました",
"imported": "正常にインポートされました"
},
"keyboard": {
"navigation": "キーボードナビゲーション:",
"shortcuts": {
"pageUp": "1ページ上にスクロール",
"pageDown": "1ページ下にスクロール",
"home": "トップにジャンプ",
"end": "ボトムにジャンプ",
"bulkMode": "一括モードを切り替え",
"search": "検索にフォーカス",
"escape": "モーダル/パネルを閉じる"
}
},
"initialization": {
"title": "初期化中",
"message": "ワークスペースを準備中...",
"status": "初期化中...",
"estimatingTime": "時間を見積もり中...",
"loras": {
"title": "LoRAマネージャーを初期化中",
"message": "LoRAキャッシュをスキャンして構築中です。数分かかる場合があります..."
},
"checkpoints": {
"title": "チェックポイントマネージャーを初期化中",
"message": "チェックポイントキャッシュをスキャンして構築中です。数分かかる場合があります..."
},
"embeddings": {
"title": "エンベディングマネージャーを初期化中",
"message": "エンベディングキャッシュをスキャンして構築中です。数分かかる場合があります..."
},
"recipes": {
"title": "レシピマネージャーを初期化中",
"message": "レシピを読み込んで処理中です。数分かかる場合があります..."
},
"statistics": {
"title": "統計を初期化中",
"message": "統計用のモデルデータを処理中です。数分かかる場合があります..."
},
"tips": {
"title": "ヒントとコツ",
"civitai": {
"title": "Civitai統合",
"description": "Civitaiアカウントを接続プロフィールアバター → 設定 → APIキー → APIキーを追加し、Loraマネージャー設定に貼り付けてください。",
"alt": "Civitai API設定"
},
"download": {
"title": "簡単ダウンロード",
"description": "Civitai URLを使用して新しいモデルを素早くダウンロードおよびインストールします。",
"alt": "Civitaiダウンロード"
},
"recipes": {
"title": "レシピを保存",
"description": "お気に入りのモデルの組み合わせを将来使用するためにレシピを作成します。",
"alt": "レシピ"
},
"filter": {
"title": "高速フィルタリング",
"description": "ヘッダーのフィルターボタンを使用してタグやベースモデルタイプでモデルをフィルタリングします。",
"alt": "モデルをフィルター"
},
"search": {
"title": "クイック検索",
"description": "Ctrl+FMacではCmd+Fを押して現在のビュー内を素早く検索します。",
"alt": "クイック検索"
}
},
"steps": {
"scanning": "モデルファイルをスキャン中...",
"processing": "メタデータを処理中...",
"building": "キャッシュを構築中...",
"finalizing": "完了中..."
}
},
"duplicates": {
"found": "{count}個の重複グループが見つかりました",
"showNotification": "重複通知を表示",
"deleteSelected": "選択項目を削除",
"exitMode": "モードを終了",
"help": {
"identicalHashes": "同一のハッシュは、名前やプレビューが異なっていても同一のモデルファイルを意味します。",
"keepOne": "1つのバージョンのみを保持しより良いメタデータ/プレビューを持つもの)、他は安全に削除してください。"
}
},
"tooltips": {
"refresh": "モデルリストを更新",
"bulkOperations": "複数のモデルを選択してバッチ操作",
"favorites": "お気に入りモデルのみ表示",
"duplicates": "重複モデルを検索・管理",
"search": "名前、タグ、その他の条件でモデルを検索",
"filter": "様々な条件でモデルをフィルター",
"sort": "異なる属性でモデルをソート",
"backToTop": "ページトップにスクロール"
}
}

453
locales/ko.json Normal file
View File

@@ -0,0 +1,453 @@
{
"common": {
"file": "파일",
"folder": "폴더",
"name": "이름",
"size": "크기",
"date": "날짜",
"type": "유형",
"path": "경로",
"fileSize": {
"zero": "0 바이트",
"bytes": "바이트",
"kb": "KB",
"mb": "MB",
"gb": "GB",
"tb": "TB"
},
"actions": {
"save": "저장",
"cancel": "취소",
"delete": "삭제",
"edit": "편집",
"copy": "복사",
"move": "이동",
"refresh": "새로고침",
"download": "다운로드",
"upload": "업로드",
"search": "검색",
"filter": "필터",
"sort": "정렬",
"select": "선택",
"selectAll": "모두 선택",
"deselectAll": "모두 선택 해제",
"confirm": "확인",
"close": "닫기",
"back": "뒤로",
"next": "다음",
"previous": "이전",
"view": "보기",
"preview": "미리보기",
"details": "세부사항",
"backToTop": "맨 위로",
"settings": "설정",
"help": "도움말",
"about": "정보"
},
"status": {
"loading": "로딩 중...",
"saving": "저장 중...",
"saved": "저장됨",
"error": "오류",
"success": "성공",
"warning": "경고",
"info": "정보",
"processing": "처리 중...",
"completed": "완료",
"failed": "실패",
"cancelled": "취소됨",
"pending": "대기 중",
"ready": "준비됨"
},
"language": {
"current": "언어",
"select": "언어 선택",
"select_help": "인터페이스 언어를 선택하세요",
"english": "영어",
"chinese_simplified": "중국어 (간체)",
"chinese_traditional": "중국어 (번체)",
"russian": "러시아어",
"german": "독일어",
"japanese": "일본어",
"korean": "한국어",
"french": "프랑스어",
"spanish": "스페인어"
}
},
"header": {
"appTitle": "LoRA 매니저",
"navigation": {
"loras": "LoRA",
"recipes": "레시피",
"checkpoints": "체크포인트",
"embeddings": "임베딩",
"statistics": "통계"
},
"search": {
"placeholder": "검색...",
"placeholders": {
"loras": "LoRA 검색...",
"recipes": "레시피 검색...",
"checkpoints": "체크포인트 검색...",
"embeddings": "임베딩 검색..."
},
"options": "검색 옵션",
"searchIn": "검색 범위:",
"notAvailable": "통계 페이지에서는 검색을 사용할 수 없습니다",
"filters": {
"filename": "파일명",
"modelname": "모델명",
"tags": "태그",
"creator": "제작자",
"title": "레시피 제목",
"loraName": "LoRA 파일명",
"loraModel": "LoRA 모델명"
}
},
"filter": {
"title": "모델 필터",
"baseModel": "베이스 모델",
"modelTags": "태그 (상위 20개)",
"clearAll": "모든 필터 지우기"
},
"theme": {
"toggle": "테마 전환",
"switchToLight": "라이트 테마로 전환",
"switchToDark": "다크 테마로 전환",
"switchToAuto": "자동 테마로 전환"
}
},
"loras": {
"title": "LoRA 모델",
"controls": {
"sort": {
"title": "모델 정렬...",
"name": "이름",
"nameAsc": "가나다순",
"nameDesc": "가나다 역순",
"date": "추가 날짜",
"dateDesc": "최신순",
"dateAsc": "오래된 순",
"size": "파일 크기",
"sizeDesc": "큰 순",
"sizeAsc": "작은 순"
},
"refresh": {
"title": "모델 목록 새로고침",
"quick": "빠른 새로고침 (증분)",
"full": "전체 재구성 (완전)"
},
"fetch": "Civitai에서 가져오기",
"download": "URL에서 다운로드",
"bulk": "일괄 작업",
"duplicates": "중복 찾기",
"favorites": "즐겨찾기만 보기"
},
"bulkOperations": {
"title": "일괄 작업",
"selected": "{count}개 선택됨",
"sendToWorkflow": "선택된 모든 LoRA를 워크플로우로 전송",
"copyAll": "선택된 모든 LoRA 구문 복사",
"refreshAll": "선택된 모델의 CivitAI 메타데이터 새로고침",
"moveAll": "선택된 모델을 폴더로 이동",
"deleteAll": "선택된 모델 삭제",
"clear": "선택 지우기"
},
"contextMenu": {
"refreshMetadata": "Civitai 데이터 새로고침",
"relinkCivitai": "Civitai에 다시 연결",
"copySyntax": "LoRA 구문 복사",
"copyFilename": "모델 파일명 복사",
"copyRecipeSyntax": "레시피 구문 복사",
"sendToWorkflowAppend": "워크플로우로 전송 (추가)",
"sendToWorkflowReplace": "워크플로우로 전송 (교체)",
"openExamplesFolder": "예제 폴더 열기",
"downloadExamples": "예제 이미지 다운로드",
"replacePreview": "미리보기 교체",
"setContentRating": "콘텐츠 등급 설정",
"moveToFolder": "폴더로 이동",
"excludeModel": "모델 제외",
"deleteModel": "모델 삭제",
"shareRecipe": "레시피 공유",
"viewAllLoras": "모든 LoRA 보기",
"downloadMissingLoras": "누락된 LoRA 다운로드",
"deleteRecipe": "레시피 삭제"
},
"modal": {
"title": "LoRA 세부사항",
"tabs": {
"examples": "예제",
"description": "모델 설명",
"recipes": "레시피"
},
"info": {
"filename": "파일명",
"modelName": "모델명",
"baseModel": "베이스 모델",
"fileSize": "파일 크기",
"dateAdded": "추가 날짜",
"triggerWords": "트리거 워드",
"description": "설명",
"tags": "태그",
"rating": "평점",
"downloads": "다운로드",
"likes": "좋아요",
"version": "버전"
},
"actions": {
"copyTriggerWords": "트리거 워드 복사",
"copyLoraName": "LoRA 이름 복사",
"sendToWorkflow": "워크플로우로 전송",
"viewOnCivitai": "Civitai에서 보기",
"downloadExamples": "예제 이미지 다운로드"
}
}
},
"recipes": {
"title": "LoRA 레시피",
"controls": {
"import": "레시피 가져오기",
"refresh": {
"title": "레시피 목록 새로고침"
},
"duplicates": {
"title": "중복 레시피 찾기"
},
"filteredByLora": "LoRA로 필터됨",
"create": "레시피 만들기",
"export": "선택 항목 내보내기",
"downloadMissing": "누락된 LoRA 다운로드"
},
"duplicates": {
"found": "{count}개의 중복 그룹을 찾았습니다",
"keepLatest": "최신 버전 유지",
"deleteSelected": "선택 항목 삭제"
},
"card": {
"author": "작성자",
"loras": "{count}개 LoRA",
"tags": "태그",
"actions": {
"sendToWorkflow": "워크플로우로 전송",
"edit": "레시피 편집",
"duplicate": "레시피 복제",
"export": "레시피 내보내기",
"delete": "레시피 삭제"
}
}
},
"checkpoints": {
"title": "체크포인트 모델",
"info": {
"filename": "파일명",
"modelName": "모델명",
"baseModel": "베이스 모델",
"fileSize": "파일 크기",
"dateAdded": "추가 날짜"
}
},
"embeddings": {
"title": "임베딩 모델",
"info": {
"filename": "파일명",
"modelName": "모델명",
"triggerWords": "트리거 워드",
"fileSize": "파일 크기",
"dateAdded": "추가 날짜"
}
},
"sidebar": {
"modelRoot": "모델 루트",
"collapseAll": "모든 폴더 접기",
"pinToggle": "사이드바 고정/해제"
},
"statistics": {
"title": "통계",
"tabs": {
"overview": "개요",
"usage": "사용 분석",
"collection": "컬렉션",
"storage": "저장소",
"insights": "인사이트"
},
"overview": {
"title": "개요",
"totalLoras": "총 LoRA 수",
"totalCheckpoints": "총 체크포인트 수",
"totalEmbeddings": "총 임베딩 수",
"totalSize": "총 크기",
"favoriteModels": "즐겨찾기 모델"
},
"charts": {
"modelsByType": "유형별 모델",
"modelsByBaseModel": "베이스 모델별",
"modelsBySize": "파일 크기별",
"modelsAddedOverTime": "시간별 추가된 모델"
}
},
"modals": {
"delete": {
"title": "삭제 확인",
"message": "이 모델을 삭제하시겠습니까?",
"warningMessage": "이 작업은 되돌릴 수 없습니다.",
"confirm": "삭제",
"cancel": "취소"
},
"exclude": {
"title": "모델 제외",
"message": "이 모델을 라이브러리에서 제외하시겠습니까?",
"confirm": "제외",
"cancel": "취소"
},
"download": {
"title": "URL에서 모델 다운로드",
"url": "Civitai URL",
"placeholder": "https://civitai.com/models/...",
"locationPreview": "다운로드 위치 미리보기",
"useDefaultPath": "기본 경로 사용",
"useDefaultPathTooltip": "활성화되면 구성된 경로 템플릿을 사용하여 파일이 자동으로 정리됩니다",
"selectRootDirectory": "루트 디렉터리 선택",
"download": "다운로드",
"cancel": "취소"
},
"move": {
"title": "모델 이동",
"selectFolder": "대상 폴더 선택",
"createFolder": "새 폴더 만들기",
"folderName": "폴더 이름",
"move": "이동",
"cancel": "취소"
},
"contentRating": {
"title": "콘텐츠 등급 설정",
"current": "현재",
"levels": {
"pg": "전체 이용가",
"pg13": "13세 이상",
"r": "제한됨",
"x": "성인 전용",
"xxx": "성인 노골적"
}
}
},
"errors": {
"general": "오류가 발생했습니다",
"networkError": "네트워크 오류입니다. 연결을 확인해주세요.",
"serverError": "서버 오류입니다. 나중에 다시 시도해주세요.",
"fileNotFound": "파일을 찾을 수 없습니다",
"invalidFile": "잘못된 파일 형식입니다",
"uploadFailed": "업로드 실패",
"downloadFailed": "다운로드 실패",
"saveFailed": "저장 실패",
"loadFailed": "로드 실패",
"deleteFailed": "삭제 실패",
"moveFailed": "이동 실패",
"copyFailed": "복사 실패",
"fetchFailed": "Civitai에서 데이터를 가져오는데 실패했습니다",
"invalidUrl": "잘못된 URL 형식입니다",
"missingPermissions": "권한이 부족합니다"
},
"success": {
"saved": "성공적으로 저장되었습니다",
"deleted": "성공적으로 삭제되었습니다",
"moved": "성공적으로 이동되었습니다",
"copied": "성공적으로 복사되었습니다",
"downloaded": "성공적으로 다운로드되었습니다",
"uploaded": "성공적으로 업로드되었습니다",
"refreshed": "성공적으로 새로고침되었습니다",
"exported": "성공적으로 내보냈습니다",
"imported": "성공적으로 가져왔습니다"
},
"keyboard": {
"navigation": "키보드 탐색:",
"shortcuts": {
"pageUp": "한 페이지 위로 스크롤",
"pageDown": "한 페이지 아래로 스크롤",
"home": "맨 위로 이동",
"end": "맨 아래로 이동",
"bulkMode": "일괄 모드 전환",
"search": "검색 포커스",
"escape": "모달/패널 닫기"
}
},
"initialization": {
"title": "초기화 중",
"message": "작업공간을 준비하고 있습니다...",
"status": "초기화 중...",
"estimatingTime": "시간 추정 중...",
"loras": {
"title": "LoRA 매니저 초기화 중",
"message": "LoRA 캐시를 스캔하고 구축하고 있습니다. 몇 분 정도 걸릴 수 있습니다..."
},
"checkpoints": {
"title": "체크포인트 매니저 초기화 중",
"message": "체크포인트 캐시를 스캔하고 구축하고 있습니다. 몇 분 정도 걸릴 수 있습니다..."
},
"embeddings": {
"title": "임베딩 매니저 초기화 중",
"message": "임베딩 캐시를 스캔하고 구축하고 있습니다. 몇 분 정도 걸릴 수 있습니다..."
},
"recipes": {
"title": "레시피 매니저 초기화 중",
"message": "레시피를 로드하고 처리하고 있습니다. 몇 분 정도 걸릴 수 있습니다..."
},
"statistics": {
"title": "통계 초기화 중",
"message": "통계를 위한 모델 데이터를 처리하고 있습니다. 몇 분 정도 걸릴 수 있습니다..."
},
"tips": {
"title": "팁과 요령",
"civitai": {
"title": "Civitai 통합",
"description": "Civitai 계정을 연결하세요: 프로필 아바타 → 설정 → API 키 → API 키 추가로 이동한 후, Lora Manager 설정에 붙여넣으세요.",
"alt": "Civitai API 설정"
},
"download": {
"title": "쉬운 다운로드",
"description": "Civitai URL을 사용하여 새 모델을 빠르게 다운로드하고 설치하세요.",
"alt": "Civitai 다운로드"
},
"recipes": {
"title": "레시피 저장",
"description": "좋아하는 모델 조합을 나중에 사용하기 위해 레시피를 만드세요.",
"alt": "레시피"
},
"filter": {
"title": "빠른 필터링",
"description": "헤더의 필터 버튼을 사용하여 태그나 베이스 모델 유형으로 모델을 필터링하세요.",
"alt": "모델 필터"
},
"search": {
"title": "빠른 검색",
"description": "Ctrl+F (Mac에서는 Cmd+F)를 눌러 현재 보기에서 빠르게 검색하세요.",
"alt": "빠른 검색"
}
},
"steps": {
"scanning": "모델 파일 스캔 중...",
"processing": "메타데이터 처리 중...",
"building": "캐시 구축 중...",
"finalizing": "완료 중..."
}
},
"duplicates": {
"found": "{count}개의 중복 그룹을 찾았습니다",
"showNotification": "중복 알림 표시",
"deleteSelected": "선택 항목 삭제",
"exitMode": "모드 종료",
"help": {
"identicalHashes": "동일한 해시는 이름이나 미리보기가 다르더라도 동일한 모델 파일을 의미합니다.",
"keepOne": "하나의 버전만 유지하고 (더 나은 메타데이터/미리보기가 있는 것을 선호) 나머지는 안전하게 삭제하세요."
}
},
"tooltips": {
"refresh": "모델 목록 새로고침",
"bulkOperations": "배치 작업을 위해 여러 모델 선택",
"favorites": "즐겨찾기 모델만 표시",
"duplicates": "중복 모델 찾기 및 관리",
"search": "이름, 태그 또는 기타 기준으로 모델 검색",
"filter": "다양한 기준으로 모델 필터링",
"sort": "다양한 속성으로 모델 정렬",
"backToTop": "페이지 맨 위로 스크롤"
}
}

453
locales/ru.json Normal file
View File

@@ -0,0 +1,453 @@
{
"common": {
"file": "Файл",
"folder": "Папка",
"name": "Имя",
"size": "Размер",
"date": "Дата",
"type": "Тип",
"path": "Путь",
"fileSize": {
"zero": "0 Байт",
"bytes": "Байт",
"kb": "КБ",
"mb": "МБ",
"gb": "ГБ",
"tb": "ТБ"
},
"actions": {
"save": "Сохранить",
"cancel": "Отмена",
"delete": "Удалить",
"edit": "Редактировать",
"copy": "Копировать",
"move": "Переместить",
"refresh": "Обновить",
"download": "Скачать",
"upload": "Загрузить",
"search": "Поиск",
"filter": "Фильтр",
"sort": "Сортировка",
"select": "Выбрать",
"selectAll": "Выбрать всё",
"deselectAll": "Отменить выбор",
"confirm": "Подтвердить",
"close": "Закрыть",
"back": "Назад",
"next": "Далее",
"previous": "Предыдущий",
"view": "Просмотр",
"preview": "Предварительный просмотр",
"details": "Детали",
"backToTop": "Наверх",
"settings": "Настройки",
"help": "Помощь",
"about": "О программе"
},
"status": {
"loading": "Загрузка...",
"saving": "Сохранение...",
"saved": "Сохранено",
"error": "Ошибка",
"success": "Успешно",
"warning": "Предупреждение",
"info": "Информация",
"processing": "Обработка...",
"completed": "Завершено",
"failed": "Неудачно",
"cancelled": "Отменено",
"pending": "Ожидание",
"ready": "Готово"
},
"language": {
"current": "Язык",
"select": "Выбрать язык",
"select_help": "Выберите предпочитаемый язык интерфейса",
"english": "Английский",
"chinese_simplified": "Китайский (упрощённый)",
"chinese_traditional": "Китайский (традиционный)",
"russian": "Русский",
"german": "Немецкий",
"japanese": "Японский",
"korean": "Корейский",
"french": "Французский",
"spanish": "Испанский"
}
},
"header": {
"appTitle": "LoRA Менеджер",
"navigation": {
"loras": "LoRA",
"recipes": "Рецепты",
"checkpoints": "Чекпойнты",
"embeddings": "Эмбеддинги",
"statistics": "Статистика"
},
"search": {
"placeholder": "Поиск...",
"placeholders": {
"loras": "Поиск LoRA...",
"recipes": "Поиск рецептов...",
"checkpoints": "Поиск чекпойнтов...",
"embeddings": "Поиск эмбеддингов..."
},
"options": "Параметры поиска",
"searchIn": "Поиск в:",
"notAvailable": "Поиск недоступен на странице статистики",
"filters": {
"filename": "Имя файла",
"modelname": "Имя модели",
"tags": "Теги",
"creator": "Создатель",
"title": "Название рецепта",
"loraName": "Имя файла LoRA",
"loraModel": "Имя модели LoRA"
}
},
"filter": {
"title": "Фильтр моделей",
"baseModel": "Базовая модель",
"modelTags": "Теги (топ 20)",
"clearAll": "Очистить все фильтры"
},
"theme": {
"toggle": "Переключить тему",
"switchToLight": "Переключить на светлую тему",
"switchToDark": "Переключить на тёмную тему",
"switchToAuto": "Переключить на автоматическую тему"
}
},
"loras": {
"title": "LoRA Модели",
"controls": {
"sort": {
"title": "Сортировать модели по...",
"name": "Имя",
"nameAsc": "А - Я",
"nameDesc": "Я - А",
"date": "Дата добавления",
"dateDesc": "Новые",
"dateAsc": "Старые",
"size": "Размер файла",
"sizeDesc": "Самые большие",
"sizeAsc": "Самые маленькие"
},
"refresh": {
"title": "Обновить список моделей",
"quick": "Быстрое обновление (инкрементное)",
"full": "Полная перестройка (полная)"
},
"fetch": "Получить с Civitai",
"download": "Скачать по URL",
"bulk": "Массовые операции",
"duplicates": "Найти дубликаты",
"favorites": "Показать только избранные"
},
"bulkOperations": {
"title": "Массовые операции",
"selected": "Выбрано {count}",
"sendToWorkflow": "Отправить все выбранные LoRA в рабочий процесс",
"copyAll": "Копировать синтаксис всех выбранных LoRA",
"refreshAll": "Обновить метаданные CivitAI для выбранных моделей",
"moveAll": "Переместить выбранные модели в папку",
"deleteAll": "Удалить выбранные модели",
"clear": "Очистить выбор"
},
"contextMenu": {
"refreshMetadata": "Обновить данные Civitai",
"relinkCivitai": "Переподключить к Civitai",
"copySyntax": "Копировать синтаксис LoRA",
"copyFilename": "Копировать имя файла модели",
"copyRecipeSyntax": "Копировать синтаксис рецепта",
"sendToWorkflowAppend": "Отправить в рабочий процесс (добавить)",
"sendToWorkflowReplace": "Отправить в рабочий процесс (заменить)",
"openExamplesFolder": "Открыть папку с примерами",
"downloadExamples": "Скачать примеры изображений",
"replacePreview": "Заменить превью",
"setContentRating": "Установить возрастной рейтинг",
"moveToFolder": "Переместить в папку",
"excludeModel": "Исключить модель",
"deleteModel": "Удалить модель",
"shareRecipe": "Поделиться рецептом",
"viewAllLoras": "Просмотреть все LoRA",
"downloadMissingLoras": "Скачать недостающие LoRA",
"deleteRecipe": "Удалить рецепт"
},
"modal": {
"title": "Детали LoRA",
"tabs": {
"examples": "Примеры",
"description": "Описание модели",
"recipes": "Рецепты"
},
"info": {
"filename": "Имя файла",
"modelName": "Имя модели",
"baseModel": "Базовая модель",
"fileSize": "Размер файла",
"dateAdded": "Дата добавления",
"triggerWords": "Ключевые слова",
"description": "Описание",
"tags": "Теги",
"rating": "Рейтинг",
"downloads": "Загрузки",
"likes": "Лайки",
"version": "Версия"
},
"actions": {
"copyTriggerWords": "Копировать ключевые слова",
"copyLoraName": "Копировать имя LoRA",
"sendToWorkflow": "Отправить в рабочий процесс",
"viewOnCivitai": "Просмотреть на Civitai",
"downloadExamples": "Скачать примеры изображений"
}
}
},
"recipes": {
"title": "LoRA Рецепты",
"controls": {
"import": "Импортировать рецепт",
"refresh": {
"title": "Обновить список рецептов"
},
"duplicates": {
"title": "Найти дублирующиеся рецепты"
},
"filteredByLora": "Отфильтровано по LoRA",
"create": "Создать рецепт",
"export": "Экспортировать выбранные",
"downloadMissing": "Скачать недостающие LoRA"
},
"duplicates": {
"found": "Найдено {count} дублирующихся групп",
"keepLatest": "Сохранить последние версии",
"deleteSelected": "Удалить выбранные"
},
"card": {
"author": "Автор",
"loras": "{count} LoRA",
"tags": "Теги",
"actions": {
"sendToWorkflow": "Отправить в рабочий процесс",
"edit": "Редактировать рецепт",
"duplicate": "Дублировать рецепт",
"export": "Экспортировать рецепт",
"delete": "Удалить рецепт"
}
}
},
"checkpoints": {
"title": "Модели чекпойнтов",
"info": {
"filename": "Имя файла",
"modelName": "Имя модели",
"baseModel": "Базовая модель",
"fileSize": "Размер файла",
"dateAdded": "Дата добавления"
}
},
"embeddings": {
"title": "Модели эмбеддингов",
"info": {
"filename": "Имя файла",
"modelName": "Имя модели",
"triggerWords": "Ключевые слова",
"fileSize": "Размер файла",
"dateAdded": "Дата добавления"
}
},
"sidebar": {
"modelRoot": "Корень моделей",
"collapseAll": "Свернуть все папки",
"pinToggle": "Закрепить/Открепить боковую панель"
},
"statistics": {
"title": "Статистика",
"tabs": {
"overview": "Обзор",
"usage": "Анализ использования",
"collection": "Коллекция",
"storage": "Хранилище",
"insights": "Аналитика"
},
"overview": {
"title": "Обзор",
"totalLoras": "Всего LoRA",
"totalCheckpoints": "Всего чекпойнтов",
"totalEmbeddings": "Всего эмбеддингов",
"totalSize": "Общий размер",
"favoriteModels": "Избранные модели"
},
"charts": {
"modelsByType": "Модели по типу",
"modelsByBaseModel": "Модели по базовой модели",
"modelsBySize": "Модели по размеру файла",
"modelsAddedOverTime": "Модели, добавленные со временем"
}
},
"modals": {
"delete": {
"title": "Подтвердить удаление",
"message": "Вы уверены, что хотите удалить эту модель?",
"warningMessage": "Это действие нельзя отменить.",
"confirm": "Удалить",
"cancel": "Отмена"
},
"exclude": {
"title": "Исключить модель",
"message": "Вы уверены, что хотите исключить эту модель из библиотеки?",
"confirm": "Исключить",
"cancel": "Отмена"
},
"download": {
"title": "Скачать модель по URL",
"url": "Civitai URL",
"placeholder": "https://civitai.com/models/...",
"locationPreview": "Предварительный просмотр места загрузки",
"useDefaultPath": "Использовать путь по умолчанию",
"useDefaultPathTooltip": "При включении файлы автоматически организуются с использованием настроенных шаблонов путей",
"selectRootDirectory": "Выбрать корневую директорию",
"download": "Скачать",
"cancel": "Отмена"
},
"move": {
"title": "Переместить модели",
"selectFolder": "Выбрать папку назначения",
"createFolder": "Создать новую папку",
"folderName": "Имя папки",
"move": "Переместить",
"cancel": "Отмена"
},
"contentRating": {
"title": "Установить возрастной рейтинг",
"current": "Текущий",
"levels": {
"pg": "Для всех",
"pg13": "13+",
"r": "Ограничено",
"x": "Только для взрослых",
"xxx": "Откровенное содержание"
}
}
},
"errors": {
"general": "Произошла ошибка",
"networkError": "Ошибка сети. Проверьте подключение.",
"serverError": "Ошибка сервера. Попробуйте ещё раз позже.",
"fileNotFound": "Файл не найден",
"invalidFile": "Неверный формат файла",
"uploadFailed": "Загрузка не удалась",
"downloadFailed": "Скачивание не удалось",
"saveFailed": "Сохранение не удалось",
"loadFailed": "Загрузка не удалась",
"deleteFailed": "Удаление не удалось",
"moveFailed": "Перемещение не удалось",
"copyFailed": "Копирование не удалось",
"fetchFailed": "Не удалось получить данные с Civitai",
"invalidUrl": "Неверный формат URL",
"missingPermissions": "Недостаточно прав"
},
"success": {
"saved": "Успешно сохранено",
"deleted": "Успешно удалено",
"moved": "Успешно перемещено",
"copied": "Успешно скопировано",
"downloaded": "Успешно скачано",
"uploaded": "Успешно загружено",
"refreshed": "Успешно обновлено",
"exported": "Успешно экспортировано",
"imported": "Успешно импортировано"
},
"keyboard": {
"navigation": "Навигация с клавиатуры:",
"shortcuts": {
"pageUp": "Прокрутить вверх на одну страницу",
"pageDown": "Прокрутить вниз на одну страницу",
"home": "Перейти наверх",
"end": "Перейти вниз",
"bulkMode": "Переключить массовый режим",
"search": "Фокус на поиске",
"escape": "Закрыть модальное окно/панель"
}
},
"initialization": {
"title": "Инициализация",
"message": "Подготовка рабочего пространства...",
"status": "Инициализация...",
"estimatingTime": "Оценка времени...",
"loras": {
"title": "Инициализация LoRA Менеджера",
"message": "Сканирование и создание кэша LoRA. Это может занять несколько минут..."
},
"checkpoints": {
"title": "Инициализация менеджера чекпойнтов",
"message": "Сканирование и создание кэша чекпойнтов. Это может занять несколько минут..."
},
"embeddings": {
"title": "Инициализация менеджера эмбеддингов",
"message": "Сканирование и создание кэша эмбеддингов. Это может занять несколько минут..."
},
"recipes": {
"title": "Инициализация менеджера рецептов",
"message": "Загрузка и обработка рецептов. Это может занять несколько минут..."
},
"statistics": {
"title": "Инициализация статистики",
"message": "Обработка данных модели для статистики. Это может занять несколько минут..."
},
"tips": {
"title": "Советы и хитрости",
"civitai": {
"title": "Интеграция с Civitai",
"description": "Подключите аккаунт Civitai: Перейдите в Аватар профиля → Настройки → API ключи → Добавить API ключ, затем вставьте его в настройки Lora Manager.",
"alt": "Настройка Civitai API"
},
"download": {
"title": "Простое скачивание",
"description": "Используйте URL Civitai для быстрого скачивания и установки новых моделей.",
"alt": "Скачивание с Civitai"
},
"recipes": {
"title": "Сохранение рецептов",
"description": "Создавайте рецепты для сохранения любимых комбинаций моделей для будущего использования.",
"alt": "Рецепты"
},
"filter": {
"title": "Быстрая фильтрация",
"description": "Фильтруйте модели по тегам или типу базовой модели, используя кнопку фильтра в заголовке.",
"alt": "Фильтр моделей"
},
"search": {
"title": "Быстрый поиск",
"description": "Нажмите Ctrl+F (Cmd+F на Mac) для быстрого поиска в текущем представлении.",
"alt": "Быстрый поиск"
}
},
"steps": {
"scanning": "Сканирование файлов моделей...",
"processing": "Обработка метаданных...",
"building": "Создание кэша...",
"finalizing": "Завершение..."
}
},
"duplicates": {
"found": "Найдено {count} дублирующихся групп",
"showNotification": "Показать уведомление о дубликатах",
"deleteSelected": "Удалить выбранные",
"exitMode": "Выйти из режима",
"help": {
"identicalHashes": "Одинаковые хэши означают одинаковые файлы моделей, даже если у них разные имена или превью.",
"keepOne": "Оставьте только одну версию (предпочтительно с лучшими метаданными/превью) и безопасно удалите остальные."
}
},
"tooltips": {
"refresh": "Обновить список моделей",
"bulkOperations": "Выбрать несколько моделей для пакетных операций",
"favorites": "Показать только избранные модели",
"duplicates": "Найти и управлять дублирующимися моделями",
"search": "Поиск моделей по имени, тегам или другим критериям",
"filter": "Фильтровать модели по различным критериям",
"sort": "Сортировать модели по разным атрибутам",
"backToTop": "Прокрутить обратно наверх страницы"
}
}

453
locales/zh-CN.json Normal file
View File

@@ -0,0 +1,453 @@
{
"common": {
"file": "文件",
"folder": "文件夹",
"name": "名称",
"size": "大小",
"date": "日期",
"type": "类型",
"path": "路径",
"fileSize": {
"zero": "0 字节",
"bytes": "字节",
"kb": "KB",
"mb": "MB",
"gb": "GB",
"tb": "TB"
},
"actions": {
"save": "保存",
"cancel": "取消",
"delete": "删除",
"edit": "编辑",
"copy": "复制",
"move": "移动",
"refresh": "刷新",
"download": "下载",
"upload": "上传",
"search": "搜索",
"filter": "筛选",
"sort": "排序",
"select": "选择",
"selectAll": "全选",
"deselectAll": "取消全选",
"confirm": "确认",
"close": "关闭",
"back": "返回",
"next": "下一步",
"previous": "上一步",
"view": "查看",
"preview": "预览",
"details": "详情",
"backToTop": "返回顶部",
"settings": "设置",
"help": "帮助",
"about": "关于"
},
"status": {
"loading": "加载中...",
"saving": "保存中...",
"saved": "已保存",
"error": "错误",
"success": "成功",
"warning": "警告",
"info": "信息",
"processing": "处理中...",
"completed": "已完成",
"failed": "失败",
"cancelled": "已取消",
"pending": "等待中",
"ready": "就绪"
},
"language": {
"current": "语言",
"select": "选择语言",
"select_help": "选择您偏好的界面语言",
"english": "英语",
"chinese_simplified": "中文(简体)",
"chinese_traditional": "中文(繁体)",
"russian": "俄语",
"german": "德语",
"japanese": "日语",
"korean": "韩语",
"french": "法语",
"spanish": "西班牙语"
}
},
"header": {
"appTitle": "LoRA 管理器",
"navigation": {
"loras": "LoRA",
"recipes": "配方",
"checkpoints": "Checkpoint",
"embeddings": "Embedding",
"statistics": "统计"
},
"search": {
"placeholder": "搜索...",
"placeholders": {
"loras": "搜索 LoRA...",
"recipes": "搜索配方...",
"checkpoints": "搜索Checkpoint...",
"embeddings": "搜索 Embedding..."
},
"options": "搜索选项",
"searchIn": "搜索范围:",
"notAvailable": "统计页面不支持搜索",
"filters": {
"filename": "文件名",
"modelname": "模型名称",
"tags": "标签",
"creator": "创作者",
"title": "配方标题",
"loraName": "LoRA 文件名",
"loraModel": "LoRA 模型名称"
}
},
"filter": {
"title": "筛选模型",
"baseModel": "基础模型",
"modelTags": "标签前20个",
"clearAll": "清除所有筛选"
},
"theme": {
"toggle": "切换主题",
"switchToLight": "切换到浅色主题",
"switchToDark": "切换到深色主题",
"switchToAuto": "切换到自动主题"
}
},
"loras": {
"title": "LoRA",
"controls": {
"sort": {
"title": "排序方式...",
"name": "名称",
"nameAsc": "A - Z",
"nameDesc": "Z - A",
"date": "添加日期",
"dateDesc": "最新",
"dateAsc": "最旧",
"size": "文件大小",
"sizeDesc": "最大",
"sizeAsc": "最小"
},
"refresh": {
"title": "刷新模型列表",
"quick": "快速刷新(增量)",
"full": "完全重建(完整)"
},
"fetch": "从 Civitai 获取",
"download": "从 URL 下载",
"bulk": "批量操作",
"duplicates": "查找重复项",
"favorites": "仅显示收藏"
},
"bulkOperations": {
"title": "批量操作",
"selected": "已选择{count}项",
"sendToWorkflow": "发送到工作流",
"copyAll": "复制LoRA语法",
"refreshAll": "刷新元数据",
"moveAll": "移动",
"deleteAll": "删除",
"clear": "清除选择"
},
"contextMenu": {
"refreshMetadata": "刷新 Civitai 数据",
"relinkCivitai": "重新链接到 Civitai",
"copySyntax": "复制 LoRA 语法",
"copyFilename": "复制模型文件名",
"copyRecipeSyntax": "复制配方语法",
"sendToWorkflowAppend": "发送到工作流(追加)",
"sendToWorkflowReplace": "发送到工作流(替换)",
"openExamplesFolder": "打开示例文件夹",
"downloadExamples": "下载示例图片",
"replacePreview": "替换预览图",
"setContentRating": "设置内容评级",
"moveToFolder": "移动到文件夹",
"excludeModel": "排除模型",
"deleteModel": "删除模型",
"shareRecipe": "分享配方",
"viewAllLoras": "查看所有 LoRA",
"downloadMissingLoras": "下载缺失的 LoRA",
"deleteRecipe": "删除配方"
},
"modal": {
"title": "LoRA 详情",
"tabs": {
"examples": "示例",
"description": "模型描述",
"recipes": "配方"
},
"info": {
"filename": "文件名",
"modelName": "模型名称",
"baseModel": "基础模型",
"fileSize": "文件大小",
"dateAdded": "添加日期",
"triggerWords": "触发词",
"description": "描述",
"tags": "标签",
"rating": "评分",
"downloads": "下载量",
"likes": "点赞数",
"version": "版本"
},
"actions": {
"copyTriggerWords": "复制触发词",
"copyLoraName": "复制 LoRA 名称",
"sendToWorkflow": "发送到工作流",
"viewOnCivitai": "在 Civitai 上查看",
"downloadExamples": "下载示例图片"
}
}
},
"recipes": {
"title": "LoRA 配方",
"controls": {
"import": "导入配方",
"refresh": {
"title": "刷新配方列表"
},
"duplicates": {
"title": "查找重复配方"
},
"filteredByLora": "按 LoRA 筛选",
"create": "创建配方",
"export": "导出选中",
"downloadMissing": "下载缺失的 LoRA"
},
"duplicates": {
"found": "发现 {count} 个重复组",
"keepLatest": "保留最新版本",
"deleteSelected": "删除选中"
},
"card": {
"author": "作者",
"loras": "{count} 个 LoRA",
"tags": "标签",
"actions": {
"sendToWorkflow": "发送到工作流",
"edit": "编辑配方",
"duplicate": "复制配方",
"export": "导出配方",
"delete": "删除配方"
}
}
},
"checkpoints": {
"title": "Checkpoint",
"info": {
"filename": "文件名",
"modelName": "模型名称",
"baseModel": "基础模型",
"fileSize": "文件大小",
"dateAdded": "添加日期"
}
},
"embeddings": {
"title": "Embedding",
"info": {
"filename": "文件名",
"modelName": "模型名称",
"triggerWords": "触发词",
"fileSize": "文件大小",
"dateAdded": "添加日期"
}
},
"sidebar": {
"modelRoot": "模型根目录",
"collapseAll": "折叠所有文件夹",
"pinToggle": "固定/取消固定侧边栏"
},
"statistics": {
"title": "统计信息",
"tabs": {
"overview": "概览",
"usage": "使用分析",
"collection": "收藏",
"storage": "存储",
"insights": "洞察"
},
"overview": {
"title": "概览",
"totalLoras": "LoRA 总数",
"totalCheckpoints": "Checkpoint总数",
"totalEmbeddings": "Embedding 总数",
"totalSize": "总大小",
"favoriteModels": "收藏模型"
},
"charts": {
"modelsByType": "按类型统计模型",
"modelsByBaseModel": "按基础模型统计",
"modelsBySize": "按文件大小统计",
"modelsAddedOverTime": "模型添加时间分布"
}
},
"modals": {
"delete": {
"title": "确认删除",
"message": "确定要删除这个模型吗?",
"warningMessage": "此操作无法撤销。",
"confirm": "删除",
"cancel": "取消"
},
"exclude": {
"title": "排除模型",
"message": "确定要从库中排除这个模型吗?",
"confirm": "排除",
"cancel": "取消"
},
"download": {
"title": "从 URL 下载模型",
"url": "Civitai URL",
"placeholder": "https://civitai.com/models/...",
"locationPreview": "下载位置预览",
"useDefaultPath": "使用默认路径",
"useDefaultPathTooltip": "启用时,文件会使用配置的路径模板自动组织",
"selectRootDirectory": "选择根目录",
"download": "下载",
"cancel": "取消"
},
"move": {
"title": "移动模型",
"selectFolder": "选择目标文件夹",
"createFolder": "创建新文件夹",
"folderName": "文件夹名称",
"move": "移动",
"cancel": "取消"
},
"contentRating": {
"title": "设置内容评级",
"current": "当前",
"levels": {
"pg": "普通级",
"pg13": "辅导级",
"r": "限制级",
"x": "成人级",
"xxx": "重口级"
}
}
},
"errors": {
"general": "发生错误",
"networkError": "网络错误,请检查您的连接。",
"serverError": "服务器错误,请稍后重试。",
"fileNotFound": "文件未找到",
"invalidFile": "无效的文件格式",
"uploadFailed": "上传失败",
"downloadFailed": "下载失败",
"saveFailed": "保存失败",
"loadFailed": "加载失败",
"deleteFailed": "删除失败",
"moveFailed": "移动失败",
"copyFailed": "复制失败",
"fetchFailed": "从 Civitai 获取数据失败",
"invalidUrl": "无效的 URL 格式",
"missingPermissions": "权限不足"
},
"success": {
"saved": "保存成功",
"deleted": "删除成功",
"moved": "移动成功",
"copied": "复制成功",
"downloaded": "下载成功",
"uploaded": "上传成功",
"refreshed": "刷新成功",
"exported": "导出成功",
"imported": "导入成功"
},
"keyboard": {
"navigation": "键盘导航:",
"shortcuts": {
"pageUp": "向上滚动一页",
"pageDown": "向下滚动一页",
"home": "跳转到顶部",
"end": "跳转到底部",
"bulkMode": "切换批量模式",
"search": "聚焦搜索框",
"escape": "关闭模态框/面板"
}
},
"initialization": {
"title": "正在初始化",
"message": "正在准备您的工作空间...",
"status": "初始化中...",
"estimatingTime": "正在估算时间...",
"loras": {
"title": "初始化 LoRA 管理器",
"message": "正在扫描并构建 LoRA 缓存,这可能需要几分钟时间..."
},
"checkpoints": {
"title": "初始化Checkpoint管理器",
"message": "正在扫描并构建Checkpoint缓存这可能需要几分钟时间..."
},
"embeddings": {
"title": "初始化 Embedding 管理器",
"message": "正在扫描并构建 Embedding 缓存,这可能需要几分钟时间..."
},
"recipes": {
"title": "初始化配方管理器",
"message": "正在加载和处理配方,这可能需要几分钟时间..."
},
"statistics": {
"title": "初始化统计信息",
"message": "正在处理模型数据以生成统计信息,这可能需要几分钟时间..."
},
"tips": {
"title": "提示与技巧",
"civitai": {
"title": "Civitai 集成",
"description": "连接您的 Civitai 账户:访问头像 → 设置 → API 密钥 → 添加 API 密钥,然后将其粘贴到 Lora 管理器设置中。",
"alt": "Civitai API 设置"
},
"download": {
"title": "轻松下载",
"description": "使用 Civitai URL 快速下载和安装新模型。",
"alt": "Civitai 下载"
},
"recipes": {
"title": "保存配方",
"description": "创建配方以保存您喜欢的模型组合供将来使用。",
"alt": "配方"
},
"filter": {
"title": "快速筛选",
"description": "使用标题中的筛选按钮按标签或基础模型类型筛选模型。",
"alt": "筛选模型"
},
"search": {
"title": "快速搜索",
"description": "按 Ctrl+FMac 上为 Cmd+F快速搜索当前视图中的内容。",
"alt": "快速搜索"
}
},
"steps": {
"scanning": "扫描模型文件...",
"processing": "处理元数据...",
"building": "构建缓存...",
"finalizing": "完成中..."
}
},
"duplicates": {
"found": "发现 {count} 个重复组",
"showNotification": "显示重复项通知",
"deleteSelected": "删除选中",
"exitMode": "退出模式",
"help": {
"identicalHashes": "相同的哈希值意味着相同的模型文件,即使它们的名称或预览图不同。",
"keepOne": "保留一个版本(最好是有更好元数据/预览图的版本),安全删除其他版本。"
}
},
"tooltips": {
"refresh": "刷新模型列表",
"bulkOperations": "选择多个模型进行批量操作",
"favorites": "仅显示收藏的模型",
"duplicates": "查找和管理重复的模型",
"search": "按名称、标签或其他条件搜索模型",
"filter": "按各种条件筛选模型",
"sort": "按不同属性排序模型",
"backToTop": "滚动回页面顶部"
}
}

453
locales/zh-TW.json Normal file
View File

@@ -0,0 +1,453 @@
{
"common": {
"file": "檔案",
"folder": "資料夾",
"name": "名稱",
"size": "大小",
"date": "日期",
"type": "類型",
"path": "路徑",
"fileSize": {
"zero": "0 位元組",
"bytes": "位元組",
"kb": "KB",
"mb": "MB",
"gb": "GB",
"tb": "TB"
},
"actions": {
"save": "儲存",
"cancel": "取消",
"delete": "刪除",
"edit": "編輯",
"copy": "複製",
"move": "移動",
"refresh": "重新整理",
"download": "下載",
"upload": "上傳",
"search": "搜尋",
"filter": "篩選",
"sort": "排序",
"select": "選擇",
"selectAll": "全選",
"deselectAll": "取消全選",
"confirm": "確認",
"close": "關閉",
"back": "返回",
"next": "下一步",
"previous": "上一步",
"view": "檢視",
"preview": "預覽",
"details": "詳情",
"backToTop": "返回頂部",
"settings": "設定",
"help": "說明",
"about": "關於"
},
"status": {
"loading": "載入中...",
"saving": "儲存中...",
"saved": "已儲存",
"error": "錯誤",
"success": "成功",
"warning": "警告",
"info": "資訊",
"processing": "處理中...",
"completed": "已完成",
"failed": "失敗",
"cancelled": "已取消",
"pending": "等待中",
"ready": "就緒"
},
"language": {
"current": "語言",
"select": "選擇語言",
"select_help": "選擇您偏好的介面語言",
"english": "英語",
"chinese_simplified": "中文(簡體)",
"chinese_traditional": "中文(繁體)",
"russian": "俄語",
"german": "德語",
"japanese": "日語",
"korean": "韓語",
"french": "法語",
"spanish": "西班牙語"
}
},
"header": {
"appTitle": "LoRA 管理器",
"navigation": {
"loras": "LoRA",
"recipes": "配方",
"checkpoints": "Checkpoint",
"embeddings": "Embedding",
"statistics": "統計"
},
"search": {
"placeholder": "搜尋...",
"placeholders": {
"loras": "搜尋 LoRA...",
"recipes": "搜尋配方...",
"checkpoints": "搜尋 Checkpoint...",
"embeddings": "搜尋 Embedding..."
},
"options": "搜尋選項",
"searchIn": "搜尋範圍:",
"notAvailable": "統計頁面不支援搜尋",
"filters": {
"filename": "檔案名稱",
"modelname": "模型名稱",
"tags": "標籤",
"creator": "創作者",
"title": "配方標題",
"loraName": "LoRA 檔案名稱",
"loraModel": "LoRA 模型名稱"
}
},
"filter": {
"title": "篩選模型",
"baseModel": "基礎模型",
"modelTags": "標籤前20個",
"clearAll": "清除所有篩選"
},
"theme": {
"toggle": "切換主題",
"switchToLight": "切換到淺色主題",
"switchToDark": "切換到深色主題",
"switchToAuto": "切換到自動主題"
}
},
"loras": {
"title": "LoRA 模型",
"controls": {
"sort": {
"title": "排序方式...",
"name": "名稱",
"nameAsc": "A - Z",
"nameDesc": "Z - A",
"date": "新增日期",
"dateDesc": "最新",
"dateAsc": "最舊",
"size": "檔案大小",
"sizeDesc": "最大",
"sizeAsc": "最小"
},
"refresh": {
"title": "重新整理模型清單",
"quick": "快速重新整理(增量)",
"full": "完全重建(完整)"
},
"fetch": "從 Civitai 取得",
"download": "從 URL 下載",
"bulk": "批次操作",
"duplicates": "尋找重複項",
"favorites": "僅顯示收藏"
},
"bulkOperations": {
"title": "批次操作",
"selected": "已選擇{count}項",
"sendToWorkflow": "傳送到工作流程",
"copyAll": "複製LoRA語法",
"refreshAll": "重新整理中繼資料",
"moveAll": "移動",
"deleteAll": "刪除",
"clear": "清除選擇"
},
"contextMenu": {
"refreshMetadata": "重新整理 Civitai 資料",
"relinkCivitai": "重新連結到 Civitai",
"copySyntax": "複製 LoRA 語法",
"copyFilename": "複製模型檔案名稱",
"copyRecipeSyntax": "複製配方語法",
"sendToWorkflowAppend": "傳送到工作流程(附加)",
"sendToWorkflowReplace": "傳送到工作流程(取代)",
"openExamplesFolder": "開啟範例資料夾",
"downloadExamples": "下載範例圖片",
"replacePreview": "取代預覽圖",
"setContentRating": "設定內容評級",
"moveToFolder": "移動到資料夾",
"excludeModel": "排除模型",
"deleteModel": "刪除模型",
"shareRecipe": "分享配方",
"viewAllLoras": "檢視所有 LoRA",
"downloadMissingLoras": "下載缺少的 LoRA",
"deleteRecipe": "刪除配方"
},
"modal": {
"title": "LoRA 詳情",
"tabs": {
"examples": "範例",
"description": "模型描述",
"recipes": "配方"
},
"info": {
"filename": "檔案名稱",
"modelName": "模型名稱",
"baseModel": "基礎模型",
"fileSize": "檔案大小",
"dateAdded": "新增日期",
"triggerWords": "觸發詞",
"description": "描述",
"tags": "標籤",
"rating": "評分",
"downloads": "下載量",
"likes": "按讚數",
"version": "版本"
},
"actions": {
"copyTriggerWords": "複製觸發詞",
"copyLoraName": "複製 LoRA 名稱",
"sendToWorkflow": "傳送到工作流程",
"viewOnCivitai": "在 Civitai 上檢視",
"downloadExamples": "下載範例圖片"
}
}
},
"recipes": {
"title": "LoRA 配方",
"controls": {
"import": "匯入配方",
"refresh": {
"title": "重新整理配方清單"
},
"duplicates": {
"title": "尋找重複配方"
},
"filteredByLora": "按 LoRA 篩選",
"create": "建立配方",
"export": "匯出已選",
"downloadMissing": "下載缺少的 LoRA"
},
"duplicates": {
"found": "發現 {count} 個重複群組",
"keepLatest": "保留最新版本",
"deleteSelected": "刪除已選"
},
"card": {
"author": "作者",
"loras": "{count} 個 LoRA",
"tags": "標籤",
"actions": {
"sendToWorkflow": "傳送到工作流程",
"edit": "編輯配方",
"duplicate": "複製配方",
"export": "匯出配方",
"delete": "刪除配方"
}
}
},
"checkpoints": {
"title": "Checkpoint 模型",
"info": {
"filename": "檔案名稱",
"modelName": "模型名稱",
"baseModel": "基礎模型",
"fileSize": "檔案大小",
"dateAdded": "新增日期"
}
},
"embeddings": {
"title": "Embedding 模型",
"info": {
"filename": "檔案名稱",
"modelName": "模型名稱",
"triggerWords": "觸發詞",
"fileSize": "檔案大小",
"dateAdded": "新增日期"
}
},
"sidebar": {
"modelRoot": "模型根目錄",
"collapseAll": "摺疊所有資料夾",
"pinToggle": "釘選/取消釘選側邊欄"
},
"statistics": {
"title": "統計資訊",
"tabs": {
"overview": "概覽",
"usage": "使用分析",
"collection": "收藏",
"storage": "儲存",
"insights": "洞察"
},
"overview": {
"title": "概覽",
"totalLoras": "LoRA 總數",
"totalCheckpoints": "Checkpoint 總數",
"totalEmbeddings": "Embedding 總數",
"totalSize": "總大小",
"favoriteModels": "收藏模型"
},
"charts": {
"modelsByType": "按類型統計模型",
"modelsByBaseModel": "按基礎模型統計",
"modelsBySize": "按檔案大小統計",
"modelsAddedOverTime": "模型新增時間分佈"
}
},
"modals": {
"delete": {
"title": "確認刪除",
"message": "確定要刪除這個模型嗎?",
"warningMessage": "此操作無法復原。",
"confirm": "刪除",
"cancel": "取消"
},
"exclude": {
"title": "排除模型",
"message": "確定要從資料庫中排除這個模型嗎?",
"confirm": "排除",
"cancel": "取消"
},
"download": {
"title": "從 URL 下載模型",
"url": "Civitai URL",
"placeholder": "https://civitai.com/models/...",
"locationPreview": "下載位置預覽",
"useDefaultPath": "使用預設路徑",
"useDefaultPathTooltip": "啟用時,檔案會使用設定的路徑範本自動組織",
"selectRootDirectory": "選擇根目錄",
"download": "下載",
"cancel": "取消"
},
"move": {
"title": "移動模型",
"selectFolder": "選擇目標資料夾",
"createFolder": "建立新資料夾",
"folderName": "資料夾名稱",
"move": "移動",
"cancel": "取消"
},
"contentRating": {
"title": "設定內容評級",
"current": "目前",
"levels": {
"pg": "普通級",
"pg13": "輔導級",
"r": "限制級",
"x": "成人級",
"xxx": "重口級"
}
}
},
"errors": {
"general": "發生錯誤",
"networkError": "網路錯誤,請檢查您的連線。",
"serverError": "伺服器錯誤,請稍後重試。",
"fileNotFound": "找不到檔案",
"invalidFile": "無效的檔案格式",
"uploadFailed": "上傳失敗",
"downloadFailed": "下載失敗",
"saveFailed": "儲存失敗",
"loadFailed": "載入失敗",
"deleteFailed": "刪除失敗",
"moveFailed": "移動失敗",
"copyFailed": "複製失敗",
"fetchFailed": "從 Civitai 取得資料失敗",
"invalidUrl": "無效的 URL 格式",
"missingPermissions": "權限不足"
},
"success": {
"saved": "儲存成功",
"deleted": "刪除成功",
"moved": "移動成功",
"copied": "複製成功",
"downloaded": "下載成功",
"uploaded": "上傳成功",
"refreshed": "重新整理成功",
"exported": "匯出成功",
"imported": "匯入成功"
},
"keyboard": {
"navigation": "鍵盤導覽:",
"shortcuts": {
"pageUp": "向上捲動一頁",
"pageDown": "向下捲動一頁",
"home": "跳轉到頂部",
"end": "跳轉到底部",
"bulkMode": "切換批次模式",
"search": "聚焦搜尋框",
"escape": "關閉對話方塊/面板"
}
},
"initialization": {
"title": "正在初始化",
"message": "正在準備您的工作空間...",
"status": "初始化中...",
"estimatingTime": "正在估算時間...",
"loras": {
"title": "初始化 LoRA 管理器",
"message": "正在掃描並建立 LoRA 快取,這可能需要幾分鐘時間..."
},
"checkpoints": {
"title": "初始化 Checkpoint 管理器",
"message": "正在掃描並建立 Checkpoint 快取,這可能需要幾分鐘時間..."
},
"embeddings": {
"title": "初始化 Embedding 管理器",
"message": "正在掃描並建立 Embedding 快取,這可能需要幾分鐘時間..."
},
"recipes": {
"title": "初始化配方管理器",
"message": "正在載入和處理配方,這可能需要幾分鐘時間..."
},
"statistics": {
"title": "初始化統計資訊",
"message": "正在處理模型資料以產生統計資訊,這可能需要幾分鐘時間..."
},
"tips": {
"title": "提示與技巧",
"civitai": {
"title": "Civitai 整合",
"description": "連接您的 Civitai 帳戶:造訪頭像 → 設定 → API 金鑰 → 新增 API 金鑰,然後將其貼上到 Lora 管理器設定中。",
"alt": "Civitai API 設定"
},
"download": {
"title": "輕鬆下載",
"description": "使用 Civitai URL 快速下載和安裝新模型。",
"alt": "Civitai 下載"
},
"recipes": {
"title": "儲存配方",
"description": "建立配方以儲存您喜歡的模型組合供將來使用。",
"alt": "配方"
},
"filter": {
"title": "快速篩選",
"description": "使用標題中的篩選按鈕按標籤或基礎模型類型篩選模型。",
"alt": "篩選模型"
},
"search": {
"title": "快速搜尋",
"description": "按 Ctrl+FMac 上為 Cmd+F快速搜尋目前檢視中的內容。",
"alt": "快速搜尋"
}
},
"steps": {
"scanning": "掃描模型檔案...",
"processing": "處理中繼資料...",
"building": "建立快取...",
"finalizing": "完成中..."
}
},
"duplicates": {
"found": "發現 {count} 個重複群組",
"showNotification": "顯示重複項通知",
"deleteSelected": "刪除已選",
"exitMode": "結束模式",
"help": {
"identicalHashes": "相同的雜湊值表示相同的模型檔案,即使它們的名稱或預覽圖不同。",
"keepOne": "只保留一個版本(最好是有更好中繼資料/預覽圖的版本),安全刪除其他版本。"
}
},
"tooltips": {
"refresh": "重新整理模型清單",
"bulkOperations": "選擇多個模型進行批次操作",
"favorites": "僅顯示收藏的模型",
"duplicates": "尋找和管理重複的模型",
"search": "按名稱、標籤或其他條件搜尋模型",
"filter": "按各種條件篩選模型",
"sort": "按不同屬性排序模型",
"backToTop": "捲動回頁面頂部"
}
}

View File

@@ -18,6 +18,7 @@ class Config:
def __init__(self):
self.templates_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'templates')
self.static_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'static')
self.i18n_path = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'locales')
# Path mapping dictionary, target to link mapping
self._path_mappings = {}
# Static route mapping dictionary, target to route mapping

View File

@@ -145,7 +145,12 @@ class LoraManager:
except Exception as e:
logger.warning(f"Failed to add static route on initialization for {target_path}: {e}")
continue
# Add static route for locales JSON files
if os.path.exists(config.i18n_path):
app.router.add_static('/locales', config.i18n_path)
logger.info(f"Added static route for locales: /locales -> {config.i18n_path}")
# Add static route for plugin assets
app.router.add_static('/loras_static', config.static_path)

View File

@@ -14,10 +14,10 @@ class ServerI18nManager:
self._load_translations()
def _load_translations(self):
"""Load all translation files from the static/js/i18n directory"""
"""Load all translation files from the locales directory"""
i18n_path = os.path.join(
os.path.dirname(os.path.dirname(os.path.dirname(__file__))),
'static', 'js', 'i18n', 'locales'
'locales'
)
if not os.path.exists(i18n_path):
@@ -26,73 +26,27 @@ class ServerI18nManager:
# Load all available locale files
for filename in os.listdir(i18n_path):
if filename.endswith('.js'):
locale_code = filename[:-3] # Remove .js extension
if filename.endswith('.json'):
locale_code = filename[:-5] # Remove .json extension
try:
self._load_locale_file(i18n_path, filename, locale_code)
except Exception as e:
logger.error(f"Error loading locale file {filename}: {e}")
def _load_locale_file(self, path: str, filename: str, locale_code: str):
"""Load a single locale file and extract translation data"""
"""Load a single locale JSON file"""
file_path = os.path.join(path, filename)
try:
with open(file_path, 'r', encoding='utf-8') as f:
content = f.read()
translations = json.load(f)
# Look for export const pattern like: export const en = { ... }
import re
# Extract the variable name and object
export_pattern = r'export\s+const\s+(\w+)\s*=\s*(\{.*\});?\s*$'
match = re.search(export_pattern, content, re.DOTALL | re.MULTILINE)
if not match:
logger.warning(f"No export const found in {filename}")
return
var_name = match.group(1)
js_object = match.group(2)
# Convert JS object to JSON
json_str = self._js_object_to_json(js_object)
# Parse as JSON
translations = json.loads(json_str)
self.translations[locale_code] = translations
logger.debug(f"Loaded translations for {locale_code} (variable: {var_name})")
logger.debug(f"Loaded translations for {locale_code} from {filename}")
except Exception as e:
logger.error(f"Error parsing locale file {filename}: {e}")
def _js_object_to_json(self, js_obj: str) -> str:
"""Convert JavaScript object to JSON string"""
import re
# Remove comments (single line and multi-line)
js_obj = re.sub(r'//.*?$', '', js_obj, flags=re.MULTILINE)
js_obj = re.sub(r'/\*.*?\*/', '', js_obj, flags=re.DOTALL)
# Replace unquoted object keys with quoted keys
js_obj = re.sub(r'(\s*)([a-zA-Z_$][a-zA-Z0-9_$]*)\s*:', r'\1"\2":', js_obj)
# Handle strings more robustly using regex
# First, find all single-quoted strings and replace them with double-quoted ones
def replace_single_quotes(match):
content = match.group(1)
# Escape any double quotes in the content
content = content.replace('"', '\\"')
# Handle escaped single quotes
content = content.replace("\\'", "'")
return f'"{content}"'
# Replace single-quoted strings with double-quoted strings
js_obj = re.sub(r"'([^'\\]*(?:\\.[^'\\]*)*)'", replace_single_quotes, js_obj)
return js_obj
def set_locale(self, locale: str):
"""Set the current locale"""
if locale in self.translations:
@@ -101,8 +55,14 @@ class ServerI18nManager:
logger.warning(f"Locale {locale} not found, using 'en'")
self.current_locale = 'en'
def get_translation(self, key: str, params: Dict[str, Any] = None) -> str:
"""Get translation for a key with optional parameters"""
def get_translation(self, key: str, params: Dict[str, Any] = None, **kwargs) -> str:
"""Get translation for a key with optional parameters (supports both dict and keyword args)"""
# Merge kwargs into params for convenience
if params is None:
params = {}
if kwargs:
params = {**params, **kwargs}
if self.current_locale not in self.translations:
return key

View File

@@ -339,6 +339,11 @@ class StandaloneLoraManager(LoraManager):
logger.warning(f"Failed to add static route on initialization for {target_path}: {e}")
continue
# Add static route for locales JSON files
if os.path.exists(config.i18n_path):
app.router.add_static('/locales', config.i18n_path)
logger.info(f"Added static route for locales: /locales -> {config.i18n_path}")
# Add static route for plugin assets
app.router.add_static('/loras_static', config.static_path)

View File

@@ -30,8 +30,6 @@ export class AppCore {
// Initialize i18n first
window.i18n = i18n;
// Load language from settings
await i18n.initializeFromSettings();
console.log(`AppCore: Language set: ${i18n.getCurrentLocale()}`);
// Initialize managers

View File

@@ -1,37 +1,89 @@
/**
* Internationalization (i18n) system for LoRA Manager
* Uses user-selected language from settings with fallback to English
* Loads JSON translation files dynamically
*/
import { en } from './locales/en.js';
import { zhCN } from './locales/zh-CN.js';
import { zhTW } from './locales/zh-TW.js';
import { ru } from './locales/ru.js';
import { de } from './locales/de.js';
import { ja } from './locales/ja.js';
import { ko } from './locales/ko.js';
import { fr } from './locales/fr.js';
import { es } from './locales/es.js';
class I18nManager {
constructor() {
this.locales = {
'en': en,
'zh-CN': zhCN,
'zh-TW': zhTW,
'zh': zhCN, // Fallback for 'zh' to 'zh-CN'
'ru': ru,
'de': de,
'ja': ja,
'ko': ko,
'fr': fr,
'es': es
this.locales = {};
this.translations = {};
this.loadedLocales = new Set();
// Available locales configuration
this.availableLocales = {
'en': { name: 'English', nativeName: 'English' },
'zh-CN': { name: 'Chinese (Simplified)', nativeName: '简体中文' },
'zh-TW': { name: 'Chinese (Traditional)', nativeName: '繁體中文' },
'zh': { name: 'Chinese (Simplified)', nativeName: '简体中文' }, // Fallback to zh-CN
'ru': { name: 'Russian', nativeName: 'Русский' },
'de': { name: 'German', nativeName: 'Deutsch' },
'ja': { name: 'Japanese', nativeName: '日本語' },
'ko': { name: 'Korean', nativeName: '한국어' },
'fr': { name: 'French', nativeName: 'Français' },
'es': { name: 'Spanish', nativeName: 'Español' }
};
this.currentLocale = this.getLanguageFromSettings();
this.translations = this.locales[this.currentLocale] || this.locales['en'];
// Initialize with current locale
this.initializeWithLocale(this.currentLocale);
}
/**
* Load translations for a specific locale from JSON file
* @param {string} locale - The locale to load
* @returns {Promise<Object>} Promise that resolves to the translation data
*/
async loadLocale(locale) {
// Handle fallback for 'zh' to 'zh-CN'
const normalizedLocale = locale === 'zh' ? 'zh-CN' : locale;
if (this.loadedLocales.has(normalizedLocale)) {
return this.locales[normalizedLocale];
}
try {
const response = await fetch(`/locales/${normalizedLocale}.json`);
if (!response.ok) {
throw new Error(`HTTP error! status: ${response.status}`);
}
const translations = await response.json();
this.locales[normalizedLocale] = translations;
this.loadedLocales.add(normalizedLocale);
// Also set for 'zh' alias
if (normalizedLocale === 'zh-CN') {
this.locales['zh'] = translations;
this.loadedLocales.add('zh');
}
return translations;
} catch (error) {
console.warn(`Failed to load locale ${normalizedLocale}:`, error);
// Fallback to English if current locale fails and it's not English
if (normalizedLocale !== 'en') {
return this.loadLocale('en');
}
// Return empty object if even English fails
return {};
}
}
/**
* Initialize with a specific locale
* @param {string} locale - The locale to initialize with
*/
async initializeWithLocale(locale) {
try {
this.translations = await this.loadLocale(locale);
this.currentLocale = locale;
} catch (error) {
console.warn(`Failed to initialize with locale ${locale}, falling back to English`, error);
this.translations = await this.loadLocale('en');
this.currentLocale = 'en';
}
}
/**
* Get language from user settings with fallback to English
* @returns {string} Language code
@@ -52,7 +104,7 @@ class I18nManager {
}
// If user has selected a language, use it
if (userLanguage && this.locales[userLanguage]) {
if (userLanguage && this.availableLocales[userLanguage]) {
return userLanguage;
}
@@ -63,20 +115,20 @@ class I18nManager {
/**
* Set the current language and save to settings
* @param {string} languageCode - The language code to set
* @returns {boolean} True if language was successfully set
* @returns {Promise<boolean>} True if language was successfully set
*/
setLanguage(languageCode) {
if (!this.locales[languageCode]) {
async setLanguage(languageCode) {
if (!this.availableLocales[languageCode]) {
console.warn(`Language '${languageCode}' is not supported`);
return false;
}
this.currentLocale = languageCode;
this.translations = this.locales[languageCode];
// Save to localStorage
const STORAGE_PREFIX = 'lora_manager_';
try {
// Load the new locale
await this.initializeWithLocale(languageCode);
// Save to localStorage
const STORAGE_PREFIX = 'lora_manager_';
const currentSettings = localStorage.getItem(STORAGE_PREFIX + 'settings');
let settings = {};
@@ -88,9 +140,15 @@ class I18nManager {
localStorage.setItem(STORAGE_PREFIX + 'settings', JSON.stringify(settings));
console.log(`Language changed to: ${languageCode}`);
// Dispatch event to notify components of language change
window.dispatchEvent(new CustomEvent('languageChanged', {
detail: { language: languageCode }
}));
return true;
} catch (e) {
console.error('Failed to save language setting:', e);
console.error('Failed to set language:', e);
return false;
}
}
@@ -100,17 +158,11 @@ class I18nManager {
* @returns {Array} Array of language objects
*/
getAvailableLanguages() {
return [
{ code: 'en', name: 'English', nativeName: 'English' },
{ code: 'zh-CN', name: 'Chinese (Simplified)', nativeName: '简体中文' },
{ code: 'zh-TW', name: 'Chinese (Traditional)', nativeName: '繁體中文' },
{ code: 'ru', name: 'Russian', nativeName: 'Русский' },
{ code: 'de', name: 'German', nativeName: 'Deutsch' },
{ code: 'ja', name: 'Japanese', nativeName: '日本語' },
{ code: 'ko', name: 'Korean', nativeName: '한국어' },
{ code: 'fr', name: 'French', nativeName: 'Français' },
{ code: 'es', name: 'Spanish', nativeName: 'Español' }
];
return Object.entries(this.availableLocales).map(([code, info]) => ({
code,
name: info.name,
nativeName: info.nativeName
}));
}
/**
@@ -129,14 +181,20 @@ class I18nManager {
value = value[k];
} else {
// Fallback to English if key not found in current locale
value = this.locales['en'];
for (const fallbackKey of keys) {
if (value && typeof value === 'object' && fallbackKey in value) {
value = value[fallbackKey];
} else {
console.warn(`Translation key not found: ${key}`);
return key; // Return key as fallback
if (this.currentLocale !== 'en' && this.locales['en']) {
let fallbackValue = this.locales['en'];
for (const fallbackKey of keys) {
if (fallbackValue && typeof fallbackValue === 'object' && fallbackKey in fallbackValue) {
fallbackValue = fallbackValue[fallbackKey];
} else {
console.warn(`Translation key not found: ${key}`);
return key; // Return key as fallback
}
}
value = fallbackValue;
} else {
console.warn(`Translation key not found: ${key}`);
return key; // Return key as fallback
}
break;
}

View File

@@ -1,397 +0,0 @@
/**
* German (de) translations for LoRA Manager
*/
export const de = {
// Allgemeine Begriffe in der Anwendung
common: {
// Dateioperationen
file: 'Datei',
folder: 'Ordner',
name: 'Name',
size: 'Größe',
date: 'Datum',
type: 'Typ',
path: 'Pfad',
// Dateigrößen
fileSize: {
zero: '0 Bytes',
bytes: 'Bytes',
kb: 'KB',
mb: 'MB',
gb: 'GB',
tb: 'TB'
},
// Aktionen
actions: {
save: 'Speichern',
cancel: 'Abbrechen',
delete: 'Löschen',
edit: 'Bearbeiten',
copy: 'Kopieren',
move: 'Verschieben',
refresh: 'Aktualisieren',
download: 'Herunterladen',
upload: 'Hochladen',
search: 'Suchen',
filter: 'Filter',
sort: 'Sortieren',
select: 'Auswählen',
selectAll: 'Alle auswählen',
deselectAll: 'Auswahl aufheben',
confirm: 'Bestätigen',
close: 'Schließen',
back: 'Zurück',
next: 'Weiter',
previous: 'Vorherige',
view: 'Anzeigen',
preview: 'Vorschau',
details: 'Details',
settings: 'Einstellungen',
help: 'Hilfe',
about: 'Über'
},
// Spracheinstellungen
language: {
current: 'Sprache',
select: 'Sprache auswählen',
select_help: 'Wählen Sie Ihre bevorzugte Oberflächensprache',
english: 'Englisch',
chinese_simplified: 'Chinesisch (vereinfacht)',
chinese_traditional: 'Chinesisch (traditionell)',
russian: 'Russisch',
german: 'Deutsch',
japanese: 'Japanisch',
korean: 'Koreanisch',
french: 'Französisch',
spanish: 'Spanisch'
},
// Statusmeldungen
status: {
loading: 'Lädt...',
saving: 'Speichere...',
saved: 'Gespeichert',
error: 'Fehler',
success: 'Erfolgreich',
warning: 'Warnung',
info: 'Information',
processing: 'Verarbeite...',
completed: 'Abgeschlossen',
failed: 'Fehlgeschlagen',
cancelled: 'Abgebrochen',
pending: 'Wartend',
ready: 'Bereit'
}
},
// Kopfzeile und Navigation
header: {
appTitle: 'LoRA Manager',
navigation: {
loras: 'LoRAs',
recipes: 'Rezepte',
checkpoints: 'Checkpoints',
embeddings: 'Embeddings',
statistics: 'Statistiken'
},
search: {
placeholder: 'Suchen...',
placeholders: {
loras: 'LoRAs suchen...',
recipes: 'Rezepte suchen...',
checkpoints: 'Checkpoints suchen...',
embeddings: 'Embeddings suchen...'
},
options: 'Suchoptionen',
searchIn: 'Suchen in:',
notAvailable: 'Suche nicht verfügbar auf der Statistikseite',
filters: {
filename: 'Dateiname',
modelname: 'Modellname',
tags: 'Tags',
creator: 'Ersteller',
title: 'Rezepttitel',
loraName: 'LoRA Dateiname',
loraModel: 'LoRA Modellname'
}
},
filter: {
title: 'Modelle filtern',
baseModel: 'Basismodell',
modelTags: 'Tags (Top 20)',
clearAll: 'Alle Filter löschen'
},
theme: {
toggle: 'Design wechseln',
switchToLight: 'Zu hellem Design wechseln',
switchToDark: 'Zu dunklem Design wechseln',
switchToAuto: 'Zu automatischem Design wechseln'
}
},
// LoRA Seite
loras: {
title: 'LoRA Modelle',
controls: {
sort: {
title: 'Modelle sortieren nach...',
name: 'Name',
nameAsc: 'A - Z',
nameDesc: 'Z - A',
date: 'Hinzufügungsdatum',
dateDesc: 'Neueste',
dateAsc: 'Älteste',
size: 'Dateigröße',
sizeDesc: 'Größte',
sizeAsc: 'Kleinste'
},
refresh: {
title: 'Modellliste aktualisieren',
quick: 'Schnelle Aktualisierung (inkrementell)',
full: 'Vollständiger Neuaufbau (komplett)'
},
fetch: 'Von Civitai abrufen',
download: 'Von URL herunterladen',
bulk: 'Massenoperationen',
duplicates: 'Duplikate finden',
favorites: 'Nur Favoriten anzeigen'
},
bulkOperations: {
title: 'Massenoperationen',
selected: '{count} ausgewählt',
selectAll: 'Alle auf aktueller Seite auswählen',
deselectAll: 'Alle abwählen',
actions: {
move: 'Ausgewählte verschieben',
delete: 'Ausgewählte löschen',
setRating: 'Inhaltsbewertung festlegen',
export: 'Ausgewählte exportieren'
}
},
card: {
actions: {
copyTriggerWords: 'Trigger-Wörter kopieren',
copyLoraName: 'LoRA-Namen kopieren',
sendToWorkflow: 'An Workflow senden',
sendToWorkflowAppend: 'An Workflow senden (anhängen)',
sendToWorkflowReplace: 'An Workflow senden (ersetzen)',
openExamples: 'Beispielordner öffnen',
downloadExamples: 'Beispielbilder herunterladen',
replacePreview: 'Vorschau ersetzen',
setContentRating: 'Inhaltsbewertung festlegen',
moveToFolder: 'In Ordner verschieben',
excludeModel: 'Modell ausschließen',
deleteModel: 'Modell löschen'
},
modal: {
title: 'LoRA Details',
tabs: {
examples: 'Beispiele',
description: 'Modellbeschreibung',
recipes: 'Rezepte'
},
info: {
filename: 'Dateiname',
modelName: 'Modellname',
baseModel: 'Basismodell',
fileSize: 'Dateigröße',
dateAdded: 'Hinzufügungsdatum',
triggerWords: 'Trigger-Wörter',
description: 'Beschreibung',
tags: 'Tags',
rating: 'Bewertung',
downloads: 'Downloads',
likes: 'Gefällt mir',
version: 'Version'
},
actions: {
copyTriggerWords: 'Trigger-Wörter kopieren',
copyLoraName: 'LoRA-Namen kopieren',
sendToWorkflow: 'An Workflow senden',
viewOnCivitai: 'Auf Civitai anzeigen',
downloadExamples: 'Beispielbilder herunterladen'
}
}
}
},
// Rezepte Seite
recipes: {
title: 'LoRA Rezepte',
controls: {
import: 'Rezept importieren',
create: 'Rezept erstellen',
export: 'Ausgewählte exportieren',
downloadMissing: 'Fehlende LoRAs herunterladen'
},
card: {
author: 'Autor',
loras: '{count} LoRAs',
tags: 'Tags',
actions: {
sendToWorkflow: 'An Workflow senden',
edit: 'Rezept bearbeiten',
duplicate: 'Rezept duplizieren',
export: 'Rezept exportieren',
delete: 'Rezept löschen'
}
}
},
// Checkpoint Seite
checkpoints: {
title: 'Checkpoint Modelle',
info: {
filename: 'Dateiname',
modelName: 'Modellname',
baseModel: 'Basismodell',
fileSize: 'Dateigröße',
dateAdded: 'Hinzufügungsdatum'
}
},
// Embeddings Seite
embeddings: {
title: 'Embedding Modelle',
info: {
filename: 'Dateiname',
modelName: 'Modellname',
triggerWords: 'Trigger-Wörter',
fileSize: 'Dateigröße',
dateAdded: 'Hinzufügungsdatum'
}
},
// Statistik Seite
statistics: {
title: 'Statistiken',
overview: {
title: 'Übersicht',
totalModels: 'Gesamte Modelle',
totalSize: 'Gesamtgröße',
avgFileSize: 'Durchschnittliche Dateigröße',
newestModel: 'Neuestes Modell'
},
charts: {
modelsByBaseModel: 'Nach Basismodell',
modelsByMonth: 'Nach Monat',
fileSizeDistribution: 'Dateigrößenverteilung',
topTags: 'Beliebte Tags'
}
},
// Modale Dialoge
modals: {
delete: {
title: 'Löschen bestätigen',
message: 'Sind Sie sicher, dass Sie dieses Modell löschen möchten? Diese Aktion kann nicht rückgängig gemacht werden.',
confirm: 'Löschen',
cancel: 'Abbrechen'
},
exclude: {
title: 'Modell ausschließen',
message: 'Sind Sie sicher, dass Sie dieses Modell aus der Bibliothek ausschließen möchten?',
confirm: 'Ausschließen',
cancel: 'Abbrechen'
},
download: {
title: 'Modell herunterladen',
url: 'Modell URL',
placeholder: 'Civitai Modell URL eingeben...',
download: 'Herunterladen',
cancel: 'Abbrechen'
},
move: {
title: 'Modell verschieben',
selectFolder: 'Zielordner auswählen',
createFolder: 'Neuen Ordner erstellen',
folderName: 'Ordnername',
move: 'Verschieben',
cancel: 'Abbrechen'
},
contentRating: {
title: 'Inhaltsbewertung festlegen',
current: 'Aktuell',
levels: {
pg: 'Allgemein',
pg13: 'Ab 13',
r: 'Eingeschränkt',
x: 'Erwachsene',
xxx: 'Explizit'
}
}
},
// Fehlermeldungen
errors: {
general: 'Ein Fehler ist aufgetreten',
networkError: 'Netzwerkfehler. Überprüfen Sie Ihre Verbindung.',
serverError: 'Serverfehler. Versuchen Sie es später erneut.',
fileNotFound: 'Datei nicht gefunden',
invalidFile: 'Ungültiges Dateiformat',
uploadFailed: 'Upload fehlgeschlagen',
downloadFailed: 'Download fehlgeschlagen',
saveFailed: 'Speichern fehlgeschlagen',
loadFailed: 'Laden fehlgeschlagen',
deleteFailed: 'Löschen fehlgeschlagen',
moveFailed: 'Verschieben fehlgeschlagen',
copyFailed: 'Kopieren fehlgeschlagen',
fetchFailed: 'Daten von Civitai konnten nicht abgerufen werden',
invalidUrl: 'Ungültiges URL-Format',
missingPermissions: 'Unzureichende Berechtigungen'
},
// Erfolgsmeldungen
success: {
saved: 'Erfolgreich gespeichert',
deleted: 'Erfolgreich gelöscht',
moved: 'Erfolgreich verschoben',
copied: 'Erfolgreich kopiert',
downloaded: 'Erfolgreich heruntergeladen',
uploaded: 'Erfolgreich hochgeladen',
refreshed: 'Erfolgreich aktualisiert',
exported: 'Erfolgreich exportiert',
imported: 'Erfolgreich importiert'
},
// Tastaturkürzel
keyboard: {
navigation: 'Tastaturnavigation:',
shortcuts: {
pageUp: 'Eine Seite nach oben scrollen',
pageDown: 'Eine Seite nach unten scrollen',
home: 'Zum Anfang springen',
end: 'Zum Ende springen',
bulkMode: 'Massenmodus umschalten',
search: 'Suche fokussieren',
escape: 'Modal/Panel schließen'
}
},
// Initialisierung
initialization: {
title: 'LoRA Manager initialisieren',
message: 'Scannen und Aufbau des LoRA-Caches. Dies kann einige Minuten dauern...',
steps: {
scanning: 'Modelldateien scannen...',
processing: 'Metadaten verarbeiten...',
building: 'Cache aufbauen...',
finalizing: 'Abschließen...'
}
},
// Tooltips und Hilfetext
tooltips: {
refresh: 'Modellliste aktualisieren',
bulkOperations: 'Mehrere Modelle für Batch-Operationen auswählen',
favorites: 'Nur Lieblingsmodelle anzeigen',
duplicates: 'Doppelte Modelle finden und verwalten',
search: 'Modelle nach Name, Tags oder anderen Kriterien suchen',
filter: 'Modelle nach verschiedenen Kriterien filtern',
sort: 'Modelle nach verschiedenen Attributen sortieren',
backToTop: 'Zurück zum Seitenanfang scrollen'
}
};

View File

@@ -1,415 +0,0 @@
/**
* English (en) translations for LoRA Manager
*/
export const en = {
// Common terms used throughout the application
common: {
// File operations
file: 'File',
folder: 'Folder',
name: 'Name',
size: 'Size',
date: 'Date',
type: 'Type',
path: 'Path',
// File sizes
fileSize: {
zero: '0 Bytes',
bytes: 'Bytes',
kb: 'KB',
mb: 'MB',
gb: 'GB',
tb: 'TB'
},
// Actions
actions: {
save: 'Save',
cancel: 'Cancel',
delete: 'Delete',
edit: 'Edit',
copy: 'Copy',
move: 'Move',
refresh: 'Refresh',
download: 'Download',
upload: 'Upload',
search: 'Search',
filter: 'Filter',
sort: 'Sort',
select: 'Select',
selectAll: 'Select All',
deselectAll: 'Deselect All',
confirm: 'Confirm',
close: 'Close',
back: 'Back',
next: 'Next',
previous: 'Previous',
view: 'View',
preview: 'Preview',
details: 'Details',
settings: 'Settings',
help: 'Help',
about: 'About'
},
// Status messages
status: {
loading: 'Loading...',
saving: 'Saving...',
saved: 'Saved',
error: 'Error',
success: 'Success',
warning: 'Warning',
info: 'Information',
processing: 'Processing...',
completed: 'Completed',
failed: 'Failed',
cancelled: 'Cancelled',
pending: 'Pending',
ready: 'Ready'
},
// Languages
language: {
current: 'Language',
select: 'Select Language',
select_help: 'Choose your preferred language for the interface',
english: 'English',
chinese_simplified: 'Chinese (Simplified)',
chinese_traditional: 'Chinese (Traditional)',
russian: 'Russian',
german: 'German',
japanese: 'Japanese',
korean: 'Korean',
french: 'French',
spanish: 'Spanish'
}
},
// Header and navigation
header: {
appTitle: 'LoRA Manager',
navigation: {
loras: 'LoRAs',
recipes: 'Recipes',
checkpoints: 'Checkpoints',
embeddings: 'Embeddings',
statistics: 'Stats'
},
search: {
placeholder: 'Search...',
placeholders: {
loras: 'Search LoRAs...',
recipes: 'Search recipes...',
checkpoints: 'Search checkpoints...',
embeddings: 'Search embeddings...'
},
options: 'Search Options',
searchIn: 'Search In:',
notAvailable: 'Search not available on statistics page',
filters: {
filename: 'Filename',
modelname: 'Model Name',
tags: 'Tags',
creator: 'Creator',
title: 'Recipe Title',
loraName: 'LoRA Filename',
loraModel: 'LoRA Model Name'
}
},
filter: {
title: 'Filter Models',
baseModel: 'Base Model',
modelTags: 'Tags (Top 20)',
clearAll: 'Clear All Filters'
},
theme: {
toggle: 'Toggle theme',
switchToLight: 'Switch to light theme',
switchToDark: 'Switch to dark theme',
switchToAuto: 'Switch to auto theme'
}
},
// LoRAs page
loras: {
title: 'LoRA Models',
controls: {
sort: {
title: 'Sort models by...',
name: 'Name',
nameAsc: 'A - Z',
nameDesc: 'Z - A',
date: 'Date Added',
dateDesc: 'Newest',
dateAsc: 'Oldest',
size: 'File Size',
sizeDesc: 'Largest',
sizeAsc: 'Smallest'
},
refresh: {
title: 'Refresh model list',
quick: 'Quick Refresh (incremental)',
full: 'Full Rebuild (complete)'
},
fetch: 'Fetch from Civitai',
download: 'Download from URL',
bulk: 'Bulk Operations',
duplicates: 'Find Duplicates',
favorites: 'Show Favorites Only'
},
bulkOperations: {
title: 'Bulk Operations',
selected: '{count} selected',
sendToWorkflow: 'Send all selected LoRAs to workflow',
copyAll: 'Copy all selected LoRAs syntax',
refreshAll: 'Refresh CivitAI metadata for selected models',
moveAll: 'Move selected models to folder',
deleteAll: 'Delete selected models',
clear: 'Clear selection'
},
contextMenu: {
refreshMetadata: 'Refresh Civitai Data',
relinkCivitai: 'Re-link to Civitai',
copySyntax: 'Copy LoRA Syntax',
sendToWorkflowAppend: 'Send to Workflow (Append)',
sendToWorkflowReplace: 'Send to Workflow (Replace)',
openExamples: 'Open Examples Folder',
downloadExamples: 'Download Example Images',
replacePreview: 'Replace Preview',
setContentRating: 'Set Content Rating',
moveToFolder: 'Move to Folder',
excludeModel: 'Exclude Model',
deleteModel: 'Delete Model'
},
modal: {
title: 'LoRA Details',
tabs: {
examples: 'Examples',
description: 'Model Description',
recipes: 'Recipes'
},
info: {
filename: 'Filename',
modelName: 'Model Name',
baseModel: 'Base Model',
fileSize: 'File Size',
dateAdded: 'Date Added',
triggerWords: 'Trigger Words',
description: 'Description',
tags: 'Tags',
rating: 'Rating',
downloads: 'Downloads',
likes: 'Likes',
version: 'Version'
},
actions: {
copyTriggerWords: 'Copy trigger words',
copyLoraName: 'Copy LoRA name',
sendToWorkflow: 'Send to Workflow',
viewOnCivitai: 'View on Civitai',
downloadExamples: 'Download example images'
}
}
},
// Recipes page
recipes: {
title: 'LoRA Recipes',
controls: {
import: 'Import Recipe',
create: 'Create Recipe',
export: 'Export Selected',
downloadMissing: 'Download Missing LoRAs'
},
card: {
author: 'Author',
loras: '{count} LoRAs',
tags: 'Tags',
actions: {
sendToWorkflow: 'Send to Workflow',
edit: 'Edit Recipe',
duplicate: 'Duplicate Recipe',
export: 'Export Recipe',
delete: 'Delete Recipe'
}
}
},
// Checkpoints page
checkpoints: {
title: 'Checkpoint Models',
info: {
filename: 'Filename',
modelName: 'Model Name',
baseModel: 'Base Model',
fileSize: 'File Size',
dateAdded: 'Date Added'
}
},
// Embeddings page
embeddings: {
title: 'Embedding Models',
info: {
filename: 'Filename',
modelName: 'Model Name',
triggerWords: 'Trigger Words',
fileSize: 'File Size',
dateAdded: 'Date Added'
}
},
// Statistics page
statistics: {
title: 'Statistics',
overview: {
title: 'Overview',
totalLoras: 'Total LoRAs',
totalCheckpoints: 'Total Checkpoints',
totalEmbeddings: 'Total Embeddings',
totalSize: 'Total Size',
favoriteModels: 'Favorite Models'
},
charts: {
modelsByType: 'Models by Type',
modelsByBaseModel: 'Models by Base Model',
modelsBySize: 'Models by File Size',
modelsAddedOverTime: 'Models Added Over Time'
}
},
// Modals and dialogs
modals: {
delete: {
title: 'Confirm Deletion',
message: 'Are you sure you want to delete this model?',
warningMessage: 'This action cannot be undone.',
confirm: 'Delete',
cancel: 'Cancel'
},
exclude: {
title: 'Exclude Model',
message: 'Are you sure you want to exclude this model from the library?',
confirm: 'Exclude',
cancel: 'Cancel'
},
download: {
title: 'Download Model',
url: 'Model URL',
placeholder: 'Enter Civitai model URL...',
download: 'Download',
cancel: 'Cancel'
},
move: {
title: 'Move Models',
selectFolder: 'Select destination folder',
createFolder: 'Create new folder',
folderName: 'Folder name',
move: 'Move',
cancel: 'Cancel'
},
contentRating: {
title: 'Set Content Rating',
current: 'Current',
levels: {
pg: 'PG',
pg13: 'PG13',
r: 'R',
x: 'X',
xxx: 'XXX'
}
}
},
// Error messages
errors: {
general: 'An error occurred',
networkError: 'Network error. Please check your connection.',
serverError: 'Server error. Please try again later.',
fileNotFound: 'File not found',
invalidFile: 'Invalid file format',
uploadFailed: 'Upload failed',
downloadFailed: 'Download failed',
saveFailed: 'Save failed',
loadFailed: 'Load failed',
deleteFailed: 'Delete failed',
moveFailed: 'Move failed',
copyFailed: 'Copy failed',
fetchFailed: 'Failed to fetch data from Civitai',
invalidUrl: 'Invalid URL format',
missingPermissions: 'Insufficient permissions'
},
// Success messages
success: {
saved: 'Successfully saved',
deleted: 'Successfully deleted',
moved: 'Successfully moved',
copied: 'Successfully copied',
downloaded: 'Successfully downloaded',
uploaded: 'Successfully uploaded',
refreshed: 'Successfully refreshed',
exported: 'Successfully exported',
imported: 'Successfully imported'
},
// Keyboard shortcuts
keyboard: {
navigation: 'Keyboard Navigation:',
shortcuts: {
pageUp: 'Scroll up one page',
pageDown: 'Scroll down one page',
home: 'Jump to top',
end: 'Jump to bottom',
bulkMode: 'Toggle bulk mode',
search: 'Focus search',
escape: 'Close modal/panel'
}
},
// Initialization
initialization: {
title: 'Initializing LoRA Manager',
message: 'Scanning and building LoRA cache. This may take a few minutes...',
loras: {
title: 'Initializing LoRA Manager',
message: 'Scanning and building LoRA cache. This may take a few minutes...'
},
checkpoints: {
title: 'Initializing Checkpoint Manager',
message: 'Scanning and building checkpoint cache. This may take a few minutes...'
},
embeddings: {
title: 'Initializing Embedding Manager',
message: 'Scanning and building embedding cache. This may take a few minutes...'
},
recipes: {
title: 'Initializing Recipe Manager',
message: 'Loading and processing recipes. This may take a few minutes...'
},
statistics: {
title: 'Initializing Statistics',
message: 'Processing model data for statistics. This may take a few minutes...'
},
steps: {
scanning: 'Scanning model files...',
processing: 'Processing metadata...',
building: 'Building cache...',
finalizing: 'Finalizing...'
}
},
// Tooltips and help text
tooltips: {
refresh: 'Refresh the model list',
bulkOperations: 'Select multiple models for batch operations',
favorites: 'Show only favorite models',
duplicates: 'Find and manage duplicate models',
search: 'Search models by name, tags, or other criteria',
filter: 'Filter models by various criteria',
sort: 'Sort models by different attributes',
backToTop: 'Scroll back to top of page'
}
};

View File

@@ -1,397 +0,0 @@
/**
* Spanish (es) translations for LoRA Manager
*/
export const es = {
// Términos comunes utilizados en la aplicación
common: {
// Operaciones de archivos
file: 'Archivo',
folder: 'Carpeta',
name: 'Nombre',
size: 'Tamaño',
date: 'Fecha',
type: 'Tipo',
path: 'Ruta',
// Tamaños de archivo
fileSize: {
zero: '0 Bytes',
bytes: 'Bytes',
kb: 'KB',
mb: 'MB',
gb: 'GB',
tb: 'TB'
},
// Acciones
actions: {
save: 'Guardar',
cancel: 'Cancelar',
delete: 'Eliminar',
edit: 'Editar',
copy: 'Copiar',
move: 'Mover',
refresh: 'Actualizar',
download: 'Descargar',
upload: 'Subir',
search: 'Buscar',
filter: 'Filtrar',
sort: 'Ordenar',
select: 'Seleccionar',
selectAll: 'Seleccionar todo',
deselectAll: 'Deseleccionar todo',
confirm: 'Confirmar',
close: 'Cerrar',
back: 'Atrás',
next: 'Siguiente',
previous: 'Anterior',
view: 'Ver',
preview: 'Vista previa',
details: 'Detalles',
settings: 'Configuración',
help: 'Ayuda',
about: 'Acerca de'
},
// Configuración de idioma
language: {
current: 'Idioma',
select: 'Seleccionar idioma',
select_help: 'Elija su idioma de interfaz preferido',
english: 'Inglés',
chinese_simplified: 'Chino (simplificado)',
chinese_traditional: 'Chino (tradicional)',
russian: 'Ruso',
german: 'Alemán',
japanese: 'Japonés',
korean: 'Coreano',
french: 'Francés',
spanish: 'Español'
},
// Mensajes de estado
status: {
loading: 'Cargando...',
saving: 'Guardando...',
saved: 'Guardado',
error: 'Error',
success: 'Éxito',
warning: 'Advertencia',
info: 'Información',
processing: 'Procesando...',
completed: 'Completado',
failed: 'Falló',
cancelled: 'Cancelado',
pending: 'Pendiente',
ready: 'Listo'
}
},
// Encabezado y navegación
header: {
appTitle: 'Gestor LoRA',
navigation: {
loras: 'LoRA',
recipes: 'Recetas',
checkpoints: 'Puntos de control',
embeddings: 'Embeddings',
statistics: 'Estadísticas'
},
search: {
placeholder: 'Buscar...',
placeholders: {
loras: 'Buscar LoRA...',
recipes: 'Buscar recetas...',
checkpoints: 'Buscar puntos de control...',
embeddings: 'Buscar embeddings...'
},
options: 'Opciones de búsqueda',
searchIn: 'Buscar en:',
notAvailable: 'Búsqueda no disponible en la página de estadísticas',
filters: {
filename: 'Nombre del archivo',
modelname: 'Nombre del modelo',
tags: 'Etiquetas',
creator: 'Creador',
title: 'Título de la receta',
loraName: 'Nombre del archivo LoRA',
loraModel: 'Nombre del modelo LoRA'
}
},
filter: {
title: 'Filtrar modelos',
baseModel: 'Modelo base',
modelTags: 'Etiquetas (Top 20)',
clearAll: 'Limpiar todos los filtros'
},
theme: {
toggle: 'Cambiar tema',
switchToLight: 'Cambiar a tema claro',
switchToDark: 'Cambiar a tema oscuro',
switchToAuto: 'Cambiar a tema automático'
}
},
// Página LoRA
loras: {
title: 'Modelos LoRA',
controls: {
sort: {
title: 'Ordenar modelos por...',
name: 'Nombre',
nameAsc: 'A - Z',
nameDesc: 'Z - A',
date: 'Fecha de agregado',
dateDesc: 'Más recientes',
dateAsc: 'Más antiguos',
size: 'Tamaño del archivo',
sizeDesc: 'Más grandes',
sizeAsc: 'Más pequeños'
},
refresh: {
title: 'Actualizar lista de modelos',
quick: 'Actualización rápida (incremental)',
full: 'Reconstrucción completa (completa)'
},
fetch: 'Obtener desde Civitai',
download: 'Descargar desde URL',
bulk: 'Operaciones en lote',
duplicates: 'Encontrar duplicados',
favorites: 'Mostrar solo favoritos'
},
bulkOperations: {
title: 'Operaciones en lote',
selected: '{count} seleccionado(s)',
selectAll: 'Seleccionar todos en la página actual',
deselectAll: 'Deseleccionar todos',
actions: {
move: 'Mover elementos seleccionados',
delete: 'Eliminar elementos seleccionados',
setRating: 'Establecer clasificación de contenido',
export: 'Exportar elementos seleccionados'
}
},
card: {
actions: {
copyTriggerWords: 'Copiar palabras clave',
copyLoraName: 'Copiar nombre LoRA',
sendToWorkflow: 'Enviar al flujo de trabajo',
sendToWorkflowAppend: 'Enviar al flujo de trabajo (agregar)',
sendToWorkflowReplace: 'Enviar al flujo de trabajo (reemplazar)',
openExamples: 'Abrir carpeta de ejemplos',
downloadExamples: 'Descargar imágenes de ejemplo',
replacePreview: 'Reemplazar vista previa',
setContentRating: 'Establecer clasificación de contenido',
moveToFolder: 'Mover a carpeta',
excludeModel: 'Excluir modelo',
deleteModel: 'Eliminar modelo'
},
modal: {
title: 'Detalles LoRA',
tabs: {
examples: 'Ejemplos',
description: 'Descripción del modelo',
recipes: 'Recetas'
},
info: {
filename: 'Nombre del archivo',
modelName: 'Nombre del modelo',
baseModel: 'Modelo base',
fileSize: 'Tamaño del archivo',
dateAdded: 'Fecha de agregado',
triggerWords: 'Palabras clave',
description: 'Descripción',
tags: 'Etiquetas',
rating: 'Calificación',
downloads: 'Descargas',
likes: 'Me gusta',
version: 'Versión'
},
actions: {
copyTriggerWords: 'Copiar palabras clave',
copyLoraName: 'Copiar nombre LoRA',
sendToWorkflow: 'Enviar al flujo de trabajo',
viewOnCivitai: 'Ver en Civitai',
downloadExamples: 'Descargar imágenes de ejemplo'
}
}
}
},
// Página de recetas
recipes: {
title: 'Recetas LoRA',
controls: {
import: 'Importar receta',
create: 'Crear receta',
export: 'Exportar elementos seleccionados',
downloadMissing: 'Descargar LoRA faltantes'
},
card: {
author: 'Autor',
loras: '{count} LoRA',
tags: 'Etiquetas',
actions: {
sendToWorkflow: 'Enviar al flujo de trabajo',
edit: 'Editar receta',
duplicate: 'Duplicar receta',
export: 'Exportar receta',
delete: 'Eliminar receta'
}
}
},
// Página de puntos de control
checkpoints: {
title: 'Modelos de puntos de control',
info: {
filename: 'Nombre del archivo',
modelName: 'Nombre del modelo',
baseModel: 'Modelo base',
fileSize: 'Tamaño del archivo',
dateAdded: 'Fecha de agregado'
}
},
// Página de embeddings
embeddings: {
title: 'Modelos de embedding',
info: {
filename: 'Nombre del archivo',
modelName: 'Nombre del modelo',
triggerWords: 'Palabras clave',
fileSize: 'Tamaño del archivo',
dateAdded: 'Fecha de agregado'
}
},
// Página de estadísticas
statistics: {
title: 'Estadísticas',
overview: {
title: 'Resumen',
totalModels: 'Total de modelos',
totalSize: 'Tamaño total',
avgFileSize: 'Tamaño promedio de archivo',
newestModel: 'Modelo más reciente'
},
charts: {
modelsByBaseModel: 'Por modelo base',
modelsByMonth: 'Por mes',
fileSizeDistribution: 'Distribución de tamaños de archivo',
topTags: 'Etiquetas populares'
}
},
// Diálogos modales
modals: {
delete: {
title: 'Confirmar eliminación',
message: '¿Estás seguro de que quieres eliminar este modelo? Esta acción no se puede deshacer.',
confirm: 'Eliminar',
cancel: 'Cancelar'
},
exclude: {
title: 'Excluir modelo',
message: '¿Estás seguro de que quieres excluir este modelo de la biblioteca?',
confirm: 'Excluir',
cancel: 'Cancelar'
},
download: {
title: 'Descargar modelo',
url: 'URL del modelo',
placeholder: 'Ingresa la URL del modelo de Civitai...',
download: 'Descargar',
cancel: 'Cancelar'
},
move: {
title: 'Mover modelo',
selectFolder: 'Seleccionar carpeta de destino',
createFolder: 'Crear nueva carpeta',
folderName: 'Nombre de la carpeta',
move: 'Mover',
cancel: 'Cancelar'
},
contentRating: {
title: 'Establecer clasificación de contenido',
current: 'Actual',
levels: {
pg: 'Apto para todos',
pg13: '13 años y más',
r: 'Restringido',
x: 'Adultos',
xxx: 'Explícito'
}
}
},
// Mensajes de error
errors: {
general: 'Ocurrió un error',
networkError: 'Error de red. Verifica tu conexión.',
serverError: 'Error del servidor. Inténtalo de nuevo más tarde.',
fileNotFound: 'Archivo no encontrado',
invalidFile: 'Formato de archivo inválido',
uploadFailed: 'Falló la subida',
downloadFailed: 'Falló la descarga',
saveFailed: 'Falló el guardado',
loadFailed: 'Falló la carga',
deleteFailed: 'Falló la eliminación',
moveFailed: 'Falló el movimiento',
copyFailed: 'Falló la copia',
fetchFailed: 'No se pudieron obtener datos de Civitai',
invalidUrl: 'Formato de URL inválido',
missingPermissions: 'Permisos insuficientes'
},
// Mensajes de éxito
success: {
saved: 'Guardado exitosamente',
deleted: 'Eliminado exitosamente',
moved: 'Movido exitosamente',
copied: 'Copiado exitosamente',
downloaded: 'Descargado exitosamente',
uploaded: 'Subido exitosamente',
refreshed: 'Actualizado exitosamente',
exported: 'Exportado exitosamente',
imported: 'Importado exitosamente'
},
// Atajos de teclado
keyboard: {
navigation: 'Navegación por teclado:',
shortcuts: {
pageUp: 'Desplazar hacia arriba una página',
pageDown: 'Desplazar hacia abajo una página',
home: 'Ir al inicio',
end: 'Ir al final',
bulkMode: 'Cambiar modo de lote',
search: 'Enfocar búsqueda',
escape: 'Cerrar modal/panel'
}
},
// Inicialización
initialization: {
title: 'Inicializando Gestor LoRA',
message: 'Escaneando y construyendo caché LoRA. Esto puede tomar algunos minutos...',
steps: {
scanning: 'Escaneando archivos de modelos...',
processing: 'Procesando metadatos...',
building: 'Construyendo caché...',
finalizing: 'Finalizando...'
}
},
// Tooltips y texto de ayuda
tooltips: {
refresh: 'Actualizar la lista de modelos',
bulkOperations: 'Seleccionar múltiples modelos para operaciones por lotes',
favorites: 'Mostrar solo modelos favoritos',
duplicates: 'Encontrar y gestionar modelos duplicados',
search: 'Buscar modelos por nombre, etiquetas u otros criterios',
filter: 'Filtrar modelos por varios criterios',
sort: 'Ordenar modelos por diferentes atributos',
backToTop: 'Volver al inicio de la página'
}
};

View File

@@ -1,397 +0,0 @@
/**
* French (fr) translations for LoRA Manager
*/
export const fr = {
// Termes communs utilisés dans l'application
common: {
// Opérations sur les fichiers
file: 'Fichier',
folder: 'Dossier',
name: 'Nom',
size: 'Taille',
date: 'Date',
type: 'Type',
path: 'Chemin',
// Tailles de fichiers
fileSize: {
zero: '0 Octets',
bytes: 'Octets',
kb: 'Ko',
mb: 'Mo',
gb: 'Go',
tb: 'To'
},
// Actions
actions: {
save: 'Enregistrer',
cancel: 'Annuler',
delete: 'Supprimer',
edit: 'Modifier',
copy: 'Copier',
move: 'Déplacer',
refresh: 'Actualiser',
download: 'Télécharger',
upload: 'Importer',
search: 'Rechercher',
filter: 'Filtrer',
sort: 'Trier',
select: 'Sélectionner',
selectAll: 'Tout sélectionner',
deselectAll: 'Tout désélectionner',
confirm: 'Confirmer',
close: 'Fermer',
back: 'Retour',
next: 'Suivant',
previous: 'Précédent',
view: 'Afficher',
preview: 'Aperçu',
details: 'Détails',
settings: 'Paramètres',
help: 'Aide',
about: 'À propos'
},
// Paramètres de langue
language: {
current: 'Langue',
select: 'Sélectionner la langue',
select_help: 'Choisissez votre langue d\'interface préférée',
english: 'Anglais',
chinese_simplified: 'Chinois (simplifié)',
chinese_traditional: 'Chinois (traditionnel)',
russian: 'Russe',
german: 'Allemand',
japanese: 'Japonais',
korean: 'Coréen',
french: 'Français',
spanish: 'Espagnol'
},
// Messages de statut
status: {
loading: 'Chargement...',
saving: 'Enregistrement...',
saved: 'Enregistré',
error: 'Erreur',
success: 'Succès',
warning: 'Avertissement',
info: 'Information',
processing: 'Traitement...',
completed: 'Terminé',
failed: 'Échec',
cancelled: 'Annulé',
pending: 'En attente',
ready: 'Prêt'
}
},
// En-tête et navigation
header: {
appTitle: 'Gestionnaire LoRA',
navigation: {
loras: 'LoRA',
recipes: 'Recettes',
checkpoints: 'Points de contrôle',
embeddings: 'Embeddings',
statistics: 'Statistiques'
},
search: {
placeholder: 'Rechercher...',
placeholders: {
loras: 'Rechercher des LoRA...',
recipes: 'Rechercher des recettes...',
checkpoints: 'Rechercher des points de contrôle...',
embeddings: 'Rechercher des embeddings...'
},
options: 'Options de recherche',
searchIn: 'Rechercher dans :',
notAvailable: 'Recherche non disponible sur la page des statistiques',
filters: {
filename: 'Nom de fichier',
modelname: 'Nom du modèle',
tags: 'Tags',
creator: 'Créateur',
title: 'Titre de la recette',
loraName: 'Nom du fichier LoRA',
loraModel: 'Nom du modèle LoRA'
}
},
filter: {
title: 'Filtrer les modèles',
baseModel: 'Modèle de base',
modelTags: 'Tags (Top 20)',
clearAll: 'Effacer tous les filtres'
},
theme: {
toggle: 'Basculer le thème',
switchToLight: 'Passer au thème clair',
switchToDark: 'Passer au thème sombre',
switchToAuto: 'Passer au thème automatique'
}
},
// Page LoRA
loras: {
title: 'Modèles LoRA',
controls: {
sort: {
title: 'Trier les modèles par...',
name: 'Nom',
nameAsc: 'A - Z',
nameDesc: 'Z - A',
date: 'Date d\'ajout',
dateDesc: 'Plus récents',
dateAsc: 'Plus anciens',
size: 'Taille du fichier',
sizeDesc: 'Plus grands',
sizeAsc: 'Plus petits'
},
refresh: {
title: 'Actualiser la liste des modèles',
quick: 'Actualisation rapide (incrémentale)',
full: 'Reconstruction complète (complète)'
},
fetch: 'Récupérer depuis Civitai',
download: 'Télécharger depuis URL',
bulk: 'Opérations en lot',
duplicates: 'Trouver les doublons',
favorites: 'Afficher seulement les favoris'
},
bulkOperations: {
title: 'Opérations en lot',
selected: '{count} sélectionné(s)',
selectAll: 'Sélectionner tous sur la page courante',
deselectAll: 'Désélectionner tous',
actions: {
move: 'Déplacer les éléments sélectionnés',
delete: 'Supprimer les éléments sélectionnés',
setRating: 'Définir la classification du contenu',
export: 'Exporter les éléments sélectionnés'
}
},
card: {
actions: {
copyTriggerWords: 'Copier les mots déclencheurs',
copyLoraName: 'Copier le nom LoRA',
sendToWorkflow: 'Envoyer au flux de travail',
sendToWorkflowAppend: 'Envoyer au flux de travail (ajouter)',
sendToWorkflowReplace: 'Envoyer au flux de travail (remplacer)',
openExamples: 'Ouvrir le dossier d\'exemples',
downloadExamples: 'Télécharger les images d\'exemple',
replacePreview: 'Remplacer l\'aperçu',
setContentRating: 'Définir la classification du contenu',
moveToFolder: 'Déplacer vers le dossier',
excludeModel: 'Exclure le modèle',
deleteModel: 'Supprimer le modèle'
},
modal: {
title: 'Détails LoRA',
tabs: {
examples: 'Exemples',
description: 'Description du modèle',
recipes: 'Recettes'
},
info: {
filename: 'Nom de fichier',
modelName: 'Nom du modèle',
baseModel: 'Modèle de base',
fileSize: 'Taille du fichier',
dateAdded: 'Date d\'ajout',
triggerWords: 'Mots déclencheurs',
description: 'Description',
tags: 'Tags',
rating: 'Évaluation',
downloads: 'Téléchargements',
likes: 'J\'aime',
version: 'Version'
},
actions: {
copyTriggerWords: 'Copier les mots déclencheurs',
copyLoraName: 'Copier le nom LoRA',
sendToWorkflow: 'Envoyer au flux de travail',
viewOnCivitai: 'Voir sur Civitai',
downloadExamples: 'Télécharger les images d\'exemple'
}
}
}
},
// Page recettes
recipes: {
title: 'Recettes LoRA',
controls: {
import: 'Importer une recette',
create: 'Créer une recette',
export: 'Exporter les éléments sélectionnés',
downloadMissing: 'Télécharger les LoRA manquants'
},
card: {
author: 'Auteur',
loras: '{count} LoRA',
tags: 'Tags',
actions: {
sendToWorkflow: 'Envoyer au flux de travail',
edit: 'Modifier la recette',
duplicate: 'Dupliquer la recette',
export: 'Exporter la recette',
delete: 'Supprimer la recette'
}
}
},
// Page points de contrôle
checkpoints: {
title: 'Modèles de points de contrôle',
info: {
filename: 'Nom de fichier',
modelName: 'Nom du modèle',
baseModel: 'Modèle de base',
fileSize: 'Taille du fichier',
dateAdded: 'Date d\'ajout'
}
},
// Page embeddings
embeddings: {
title: 'Modèles d\'embedding',
info: {
filename: 'Nom de fichier',
modelName: 'Nom du modèle',
triggerWords: 'Mots déclencheurs',
fileSize: 'Taille du fichier',
dateAdded: 'Date d\'ajout'
}
},
// Page statistiques
statistics: {
title: 'Statistiques',
overview: {
title: 'Aperçu',
totalModels: 'Total des modèles',
totalSize: 'Taille totale',
avgFileSize: 'Taille moyenne des fichiers',
newestModel: 'Modèle le plus récent'
},
charts: {
modelsByBaseModel: 'Par modèle de base',
modelsByMonth: 'Par mois',
fileSizeDistribution: 'Distribution des tailles de fichier',
topTags: 'Tags populaires'
}
},
// Boîtes de dialogue modales
modals: {
delete: {
title: 'Confirmer la suppression',
message: 'Êtes-vous sûr de vouloir supprimer ce modèle ? Cette action ne peut pas être annulée.',
confirm: 'Supprimer',
cancel: 'Annuler'
},
exclude: {
title: 'Exclure le modèle',
message: 'Êtes-vous sûr de vouloir exclure ce modèle de la bibliothèque ?',
confirm: 'Exclure',
cancel: 'Annuler'
},
download: {
title: 'Télécharger le modèle',
url: 'URL du modèle',
placeholder: 'Entrer l\'URL du modèle Civitai...',
download: 'Télécharger',
cancel: 'Annuler'
},
move: {
title: 'Déplacer le modèle',
selectFolder: 'Sélectionner le dossier de destination',
createFolder: 'Créer un nouveau dossier',
folderName: 'Nom du dossier',
move: 'Déplacer',
cancel: 'Annuler'
},
contentRating: {
title: 'Définir la classification du contenu',
current: 'Actuel',
levels: {
pg: 'Tout public',
pg13: '13 ans et plus',
r: 'Restreint',
x: 'Adulte',
xxx: 'Explicite'
}
}
},
// Messages d'erreur
errors: {
general: 'Une erreur s\'est produite',
networkError: 'Erreur réseau. Vérifiez votre connexion.',
serverError: 'Erreur serveur. Veuillez réessayer plus tard.',
fileNotFound: 'Fichier non trouvé',
invalidFile: 'Format de fichier invalide',
uploadFailed: 'Échec de l\'import',
downloadFailed: 'Échec du téléchargement',
saveFailed: 'Échec de l\'enregistrement',
loadFailed: 'Échec du chargement',
deleteFailed: 'Échec de la suppression',
moveFailed: 'Échec du déplacement',
copyFailed: 'Échec de la copie',
fetchFailed: 'Impossible de récupérer les données de Civitai',
invalidUrl: 'Format d\'URL invalide',
missingPermissions: 'Permissions insuffisantes'
},
// Messages de succès
success: {
saved: 'Enregistré avec succès',
deleted: 'Supprimé avec succès',
moved: 'Déplacé avec succès',
copied: 'Copié avec succès',
downloaded: 'Téléchargé avec succès',
uploaded: 'Importé avec succès',
refreshed: 'Actualisé avec succès',
exported: 'Exporté avec succès',
imported: 'Importé avec succès'
},
// Raccourcis clavier
keyboard: {
navigation: 'Navigation au clavier :',
shortcuts: {
pageUp: 'Défiler d\'une page vers le haut',
pageDown: 'Défiler d\'une page vers le bas',
home: 'Aller au début',
end: 'Aller à la fin',
bulkMode: 'Basculer le mode lot',
search: 'Focus sur la recherche',
escape: 'Fermer modal/panneau'
}
},
// Initialisation
initialization: {
title: 'Initialisation du gestionnaire LoRA',
message: 'Analyse et construction du cache LoRA. Cela peut prendre quelques minutes...',
steps: {
scanning: 'Analyse des fichiers de modèles...',
processing: 'Traitement des métadonnées...',
building: 'Construction du cache...',
finalizing: 'Finalisation...'
}
},
// Infobulles et texte d'aide
tooltips: {
refresh: 'Actualiser la liste des modèles',
bulkOperations: 'Sélectionner plusieurs modèles pour des opérations par lot',
favorites: 'Afficher seulement les modèles favoris',
duplicates: 'Trouver et gérer les modèles en double',
search: 'Rechercher des modèles par nom, tags ou autres critères',
filter: 'Filtrer les modèles selon divers critères',
sort: 'Trier les modèles selon différents attributs',
backToTop: 'Revenir en haut de la page'
}
};

View File

@@ -1,397 +0,0 @@
/**
* Japanese (ja) translations for LoRA Manager
*/
export const ja = {
// アプリケーション全体で使用される共通用語
common: {
// ファイル操作
file: 'ファイル',
folder: 'フォルダ',
name: '名前',
size: 'サイズ',
date: '日付',
type: '種類',
path: 'パス',
// ファイルサイズ
fileSize: {
zero: '0 バイト',
bytes: 'バイト',
kb: 'KB',
mb: 'MB',
gb: 'GB',
tb: 'TB'
},
// アクション
actions: {
save: '保存',
cancel: 'キャンセル',
delete: '削除',
edit: '編集',
copy: 'コピー',
move: '移動',
refresh: '更新',
download: 'ダウンロード',
upload: 'アップロード',
search: '検索',
filter: 'フィルター',
sort: 'ソート',
select: '選択',
selectAll: 'すべて選択',
deselectAll: '選択解除',
confirm: '確認',
close: '閉じる',
back: '戻る',
next: '次へ',
previous: '前へ',
view: '表示',
preview: 'プレビュー',
details: '詳細',
settings: '設定',
help: 'ヘルプ',
about: 'について'
},
// 言語設定
language: {
current: '言語',
select: '言語を選択',
select_help: 'インターフェース言語を選択してください',
english: '英語',
chinese_simplified: '中国語(簡体字)',
chinese_traditional: '中国語(繁体字)',
russian: 'ロシア語',
german: 'ドイツ語',
japanese: '日本語',
korean: '韓国語',
french: 'フランス語',
spanish: 'スペイン語'
},
// ステータスメッセージ
status: {
loading: '読み込み中...',
saving: '保存中...',
saved: '保存済み',
error: 'エラー',
success: '成功',
warning: '警告',
info: '情報',
processing: '処理中...',
completed: '完了',
failed: '失敗',
cancelled: 'キャンセル',
pending: '待機中',
ready: '準備完了'
}
},
// ヘッダーとナビゲーション
header: {
appTitle: 'LoRA マネージャー',
navigation: {
loras: 'LoRA',
recipes: 'レシピ',
checkpoints: 'チェックポイント',
embeddings: 'エンベディング',
statistics: '統計'
},
search: {
placeholder: '検索...',
placeholders: {
loras: 'LoRAを検索...',
recipes: 'レシピを検索...',
checkpoints: 'チェックポイントを検索...',
embeddings: 'エンベディングを検索...'
},
options: '検索オプション',
searchIn: '検索対象:',
notAvailable: '統計ページでは検索は利用できません',
filters: {
filename: 'ファイル名',
modelname: 'モデル名',
tags: 'タグ',
creator: '作成者',
title: 'レシピタイトル',
loraName: 'LoRAファイル名',
loraModel: 'LoRAモデル名'
}
},
filter: {
title: 'モデルをフィルター',
baseModel: 'ベースモデル',
modelTags: 'タグトップ20',
clearAll: 'すべてのフィルターをクリア'
},
theme: {
toggle: 'テーマ切り替え',
switchToLight: 'ライトテーマに切り替え',
switchToDark: 'ダークテーマに切り替え',
switchToAuto: 'オートテーマに切り替え'
}
},
// LoRAページ
loras: {
title: 'LoRAモデル',
controls: {
sort: {
title: 'モデルをソート...',
name: '名前',
nameAsc: 'A - Z',
nameDesc: 'Z - A',
date: '追加日',
dateDesc: '新しい順',
dateAsc: '古い順',
size: 'ファイルサイズ',
sizeDesc: '大きい順',
sizeAsc: '小さい順'
},
refresh: {
title: 'モデルリストを更新',
quick: 'クイック更新(増分)',
full: '完全再構築(完全)'
},
fetch: 'Civitaiから取得',
download: 'URLからダウンロード',
bulk: '一括操作',
duplicates: '重複を検索',
favorites: 'お気に入りのみ表示'
},
bulkOperations: {
title: '一括操作',
selected: '{count}個選択中',
selectAll: '現在のページのすべてを選択',
deselectAll: 'すべての選択を解除',
actions: {
move: '選択項目を移動',
delete: '選択項目を削除',
setRating: 'コンテンツレーティングを設定',
export: '選択項目をエクスポート'
}
},
card: {
actions: {
copyTriggerWords: 'トリガーワードをコピー',
copyLoraName: 'LoRA名をコピー',
sendToWorkflow: 'ワークフローに送信',
sendToWorkflowAppend: 'ワークフローに送信(追加)',
sendToWorkflowReplace: 'ワークフローに送信(置換)',
openExamples: 'サンプルフォルダを開く',
downloadExamples: 'サンプル画像をダウンロード',
replacePreview: 'プレビューを置換',
setContentRating: 'コンテンツレーティングを設定',
moveToFolder: 'フォルダに移動',
excludeModel: 'モデルを除外',
deleteModel: 'モデルを削除'
},
modal: {
title: 'LoRA詳細',
tabs: {
examples: 'サンプル',
description: 'モデル説明',
recipes: 'レシピ'
},
info: {
filename: 'ファイル名',
modelName: 'モデル名',
baseModel: 'ベースモデル',
fileSize: 'ファイルサイズ',
dateAdded: '追加日',
triggerWords: 'トリガーワード',
description: '説明',
tags: 'タグ',
rating: '評価',
downloads: 'ダウンロード数',
likes: 'いいね数',
version: 'バージョン'
},
actions: {
copyTriggerWords: 'トリガーワードをコピー',
copyLoraName: 'LoRA名をコピー',
sendToWorkflow: 'ワークフローに送信',
viewOnCivitai: 'Civitaiで表示',
downloadExamples: 'サンプル画像をダウンロード'
}
}
}
},
// レシピページ
recipes: {
title: 'LoRAレシピ',
controls: {
import: 'レシピをインポート',
create: 'レシピを作成',
export: '選択項目をエクスポート',
downloadMissing: '不足しているLoRAをダウンロード'
},
card: {
author: '作者',
loras: '{count}個のLoRA',
tags: 'タグ',
actions: {
sendToWorkflow: 'ワークフローに送信',
edit: 'レシピを編集',
duplicate: 'レシピを複製',
export: 'レシピをエクスポート',
delete: 'レシピを削除'
}
}
},
// チェックポイントページ
checkpoints: {
title: 'チェックポイントモデル',
info: {
filename: 'ファイル名',
modelName: 'モデル名',
baseModel: 'ベースモデル',
fileSize: 'ファイルサイズ',
dateAdded: '追加日'
}
},
// エンベディングページ
embeddings: {
title: 'エンベディングモデル',
info: {
filename: 'ファイル名',
modelName: 'モデル名',
triggerWords: 'トリガーワード',
fileSize: 'ファイルサイズ',
dateAdded: '追加日'
}
},
// 統計ページ
statistics: {
title: '統計',
overview: {
title: '概要',
totalModels: '総モデル数',
totalSize: '総サイズ',
avgFileSize: '平均ファイルサイズ',
newestModel: '最新モデル'
},
charts: {
modelsByBaseModel: 'ベースモデル別',
modelsByMonth: '月別',
fileSizeDistribution: 'ファイルサイズ分布',
topTags: '人気タグ'
}
},
// モーダルダイアログ
modals: {
delete: {
title: '削除の確認',
message: 'このモデルを削除してもよろしいですか?この操作は元に戻せません。',
confirm: '削除',
cancel: 'キャンセル'
},
exclude: {
title: 'モデルを除外',
message: 'このモデルをライブラリから除外してもよろしいですか?',
confirm: '除外',
cancel: 'キャンセル'
},
download: {
title: 'モデルをダウンロード',
url: 'モデルURL',
placeholder: 'CivitaiモデルURLを入力...',
download: 'ダウンロード',
cancel: 'キャンセル'
},
move: {
title: 'モデルを移動',
selectFolder: '移動先フォルダを選択',
createFolder: '新しいフォルダを作成',
folderName: 'フォルダ名',
move: '移動',
cancel: 'キャンセル'
},
contentRating: {
title: 'コンテンツレーティングを設定',
current: '現在',
levels: {
pg: '全年齢',
pg13: '13歳以上',
r: '制限あり',
x: '成人向け',
xxx: '露骨'
}
}
},
// エラーメッセージ
errors: {
general: 'エラーが発生しました',
networkError: 'ネットワークエラー。接続を確認してください。',
serverError: 'サーバーエラー。後でもう一度試してください。',
fileNotFound: 'ファイルが見つかりません',
invalidFile: '無効なファイル形式',
uploadFailed: 'アップロードに失敗しました',
downloadFailed: 'ダウンロードに失敗しました',
saveFailed: '保存に失敗しました',
loadFailed: '読み込みに失敗しました',
deleteFailed: '削除に失敗しました',
moveFailed: '移動に失敗しました',
copyFailed: 'コピーに失敗しました',
fetchFailed: 'Civitaiからデータを取得できませんでした',
invalidUrl: '無効なURL形式',
missingPermissions: '権限が不足しています'
},
// 成功メッセージ
success: {
saved: '正常に保存されました',
deleted: '正常に削除されました',
moved: '正常に移動されました',
copied: '正常にコピーされました',
downloaded: '正常にダウンロードされました',
uploaded: '正常にアップロードされました',
refreshed: '正常に更新されました',
exported: '正常にエクスポートされました',
imported: '正常にインポートされました'
},
// キーボードショートカット
keyboard: {
navigation: 'キーボードナビゲーション:',
shortcuts: {
pageUp: '1ページ上にスクロール',
pageDown: '1ページ下にスクロール',
home: 'トップにジャンプ',
end: 'ボトムにジャンプ',
bulkMode: '一括モードを切り替え',
search: '検索にフォーカス',
escape: 'モーダル/パネルを閉じる'
}
},
// 初期化
initialization: {
title: 'LoRAマネージャーを初期化中',
message: 'LoRAキャッシュをスキャンして構築中です。数分かかる場合があります...',
steps: {
scanning: 'モデルファイルをスキャン中...',
processing: 'メタデータを処理中...',
building: 'キャッシュを構築中...',
finalizing: '完了中...'
}
},
// ツールチップとヘルプテキスト
tooltips: {
refresh: 'モデルリストを更新',
bulkOperations: '複数のモデルを選択してバッチ操作',
favorites: 'お気に入りモデルのみ表示',
duplicates: '重複モデルを検索・管理',
search: '名前、タグ、その他の条件でモデルを検索',
filter: '様々な条件でモデルをフィルター',
sort: '異なる属性でモデルをソート',
backToTop: 'ページトップにスクロール'
}
};

View File

@@ -1,397 +0,0 @@
/**
* Korean (ko) translations for LoRA Manager
*/
export const ko = {
// 애플리케이션 전체에서 사용되는 공통 용어
common: {
// 파일 작업
file: '파일',
folder: '폴더',
name: '이름',
size: '크기',
date: '날짜',
type: '유형',
path: '경로',
// 파일 크기
fileSize: {
zero: '0 바이트',
bytes: '바이트',
kb: 'KB',
mb: 'MB',
gb: 'GB',
tb: 'TB'
},
// 작업
actions: {
save: '저장',
cancel: '취소',
delete: '삭제',
edit: '편집',
copy: '복사',
move: '이동',
refresh: '새로고침',
download: '다운로드',
upload: '업로드',
search: '검색',
filter: '필터',
sort: '정렬',
select: '선택',
selectAll: '모두 선택',
deselectAll: '선택 해제',
confirm: '확인',
close: '닫기',
back: '뒤로',
next: '다음',
previous: '이전',
view: '보기',
preview: '미리보기',
details: '세부정보',
settings: '설정',
help: '도움말',
about: '정보'
},
// 언어 설정
language: {
current: '언어',
select: '언어 선택',
select_help: '선호하는 인터페이스 언어를 선택하세요',
english: '영어',
chinese_simplified: '중국어(간체)',
chinese_traditional: '중국어(번체)',
russian: '러시아어',
german: '독일어',
japanese: '일본어',
korean: '한국어',
french: '프랑스어',
spanish: '스페인어'
},
// 상태 메시지
status: {
loading: '로딩 중...',
saving: '저장 중...',
saved: '저장됨',
error: '오류',
success: '성공',
warning: '경고',
info: '정보',
processing: '처리 중...',
completed: '완료',
failed: '실패',
cancelled: '취소됨',
pending: '대기 중',
ready: '준비 완료'
}
},
// 헤더 및 네비게이션
header: {
appTitle: 'LoRA 매니저',
navigation: {
loras: 'LoRA',
recipes: '레시피',
checkpoints: '체크포인트',
embeddings: '임베딩',
statistics: '통계'
},
search: {
placeholder: '검색...',
placeholders: {
loras: 'LoRA 검색...',
recipes: '레시피 검색...',
checkpoints: '체크포인트 검색...',
embeddings: '임베딩 검색...'
},
options: '검색 옵션',
searchIn: '검색 범위:',
notAvailable: '통계 페이지에서는 검색이 불가능합니다',
filters: {
filename: '파일명',
modelname: '모델명',
tags: '태그',
creator: '제작자',
title: '레시피 제목',
loraName: 'LoRA 파일명',
loraModel: 'LoRA 모델명'
}
},
filter: {
title: '모델 필터',
baseModel: '베이스 모델',
modelTags: '태그 (상위 20개)',
clearAll: '모든 필터 지우기'
},
theme: {
toggle: '테마 전환',
switchToLight: '밝은 테마로 전환',
switchToDark: '어두운 테마로 전환',
switchToAuto: '자동 테마로 전환'
}
},
// LoRA 페이지
loras: {
title: 'LoRA 모델',
controls: {
sort: {
title: '모델 정렬...',
name: '이름',
nameAsc: 'A - Z',
nameDesc: 'Z - A',
date: '추가 날짜',
dateDesc: '최신순',
dateAsc: '오래된순',
size: '파일 크기',
sizeDesc: '큰 순서',
sizeAsc: '작은 순서'
},
refresh: {
title: '모델 목록 새로고침',
quick: '빠른 새로고침 (증분)',
full: '전체 재구축 (완전)'
},
fetch: 'Civitai에서 가져오기',
download: 'URL에서 다운로드',
bulk: '일괄 작업',
duplicates: '중복 찾기',
favorites: '즐겨찾기만 표시'
},
bulkOperations: {
title: '일괄 작업',
selected: '{count}개 선택됨',
selectAll: '현재 페이지 모두 선택',
deselectAll: '모든 선택 해제',
actions: {
move: '선택항목 이동',
delete: '선택항목 삭제',
setRating: '콘텐츠 등급 설정',
export: '선택항목 내보내기'
}
},
card: {
actions: {
copyTriggerWords: '트리거 단어 복사',
copyLoraName: 'LoRA 이름 복사',
sendToWorkflow: '워크플로우로 전송',
sendToWorkflowAppend: '워크플로우로 전송 (추가)',
sendToWorkflowReplace: '워크플로우로 전송 (교체)',
openExamples: '예제 폴더 열기',
downloadExamples: '예제 이미지 다운로드',
replacePreview: '미리보기 교체',
setContentRating: '콘텐츠 등급 설정',
moveToFolder: '폴더로 이동',
excludeModel: '모델 제외',
deleteModel: '모델 삭제'
},
modal: {
title: 'LoRA 세부정보',
tabs: {
examples: '예제',
description: '모델 설명',
recipes: '레시피'
},
info: {
filename: '파일명',
modelName: '모델명',
baseModel: '베이스 모델',
fileSize: '파일 크기',
dateAdded: '추가 날짜',
triggerWords: '트리거 단어',
description: '설명',
tags: '태그',
rating: '평점',
downloads: '다운로드 수',
likes: '좋아요 수',
version: '버전'
},
actions: {
copyTriggerWords: '트리거 단어 복사',
copyLoraName: 'LoRA 이름 복사',
sendToWorkflow: '워크플로우로 전송',
viewOnCivitai: 'Civitai에서 보기',
downloadExamples: '예제 이미지 다운로드'
}
}
}
},
// 레시피 페이지
recipes: {
title: 'LoRA 레시피',
controls: {
import: '레시피 가져오기',
create: '레시피 만들기',
export: '선택항목 내보내기',
downloadMissing: '누락된 LoRA 다운로드'
},
card: {
author: '저자',
loras: '{count}개의 LoRA',
tags: '태그',
actions: {
sendToWorkflow: '워크플로우로 전송',
edit: '레시피 편집',
duplicate: '레시피 복제',
export: '레시피 내보내기',
delete: '레시피 삭제'
}
}
},
// 체크포인트 페이지
checkpoints: {
title: '체크포인트 모델',
info: {
filename: '파일명',
modelName: '모델명',
baseModel: '베이스 모델',
fileSize: '파일 크기',
dateAdded: '추가 날짜'
}
},
// 임베딩 페이지
embeddings: {
title: '임베딩 모델',
info: {
filename: '파일명',
modelName: '모델명',
triggerWords: '트리거 단어',
fileSize: '파일 크기',
dateAdded: '추가 날짜'
}
},
// 통계 페이지
statistics: {
title: '통계',
overview: {
title: '개요',
totalModels: '총 모델 수',
totalSize: '총 크기',
avgFileSize: '평균 파일 크기',
newestModel: '최신 모델'
},
charts: {
modelsByBaseModel: '베이스 모델별',
modelsByMonth: '월별',
fileSizeDistribution: '파일 크기 분포',
topTags: '인기 태그'
}
},
// 모달 대화상자
modals: {
delete: {
title: '삭제 확인',
message: '이 모델을 삭제하시겠습니까? 이 작업은 되돌릴 수 없습니다.',
confirm: '삭제',
cancel: '취소'
},
exclude: {
title: '모델 제외',
message: '이 모델을 라이브러리에서 제외하시겠습니까?',
confirm: '제외',
cancel: '취소'
},
download: {
title: '모델 다운로드',
url: '모델 URL',
placeholder: 'Civitai 모델 URL 입력...',
download: '다운로드',
cancel: '취소'
},
move: {
title: '모델 이동',
selectFolder: '대상 폴더 선택',
createFolder: '새 폴더 만들기',
folderName: '폴더명',
move: '이동',
cancel: '취소'
},
contentRating: {
title: '콘텐츠 등급 설정',
current: '현재',
levels: {
pg: '전체관람가',
pg13: '13세 이상',
r: '제한관람가',
x: '성인',
xxx: '노골적'
}
}
},
// 오류 메시지
errors: {
general: '오류가 발생했습니다',
networkError: '네트워크 오류. 연결을 확인하세요.',
serverError: '서버 오류. 나중에 다시 시도하세요.',
fileNotFound: '파일을 찾을 수 없습니다',
invalidFile: '잘못된 파일 형식',
uploadFailed: '업로드 실패',
downloadFailed: '다운로드 실패',
saveFailed: '저장 실패',
loadFailed: '로드 실패',
deleteFailed: '삭제 실패',
moveFailed: '이동 실패',
copyFailed: '복사 실패',
fetchFailed: 'Civitai에서 데이터를 가져오지 못했습니다',
invalidUrl: '잘못된 URL 형식',
missingPermissions: '권한이 부족합니다'
},
// 성공 메시지
success: {
saved: '성공적으로 저장되었습니다',
deleted: '성공적으로 삭제되었습니다',
moved: '성공적으로 이동되었습니다',
copied: '성공적으로 복사되었습니다',
downloaded: '성공적으로 다운로드되었습니다',
uploaded: '성공적으로 업로드되었습니다',
refreshed: '성공적으로 새로고침되었습니다',
exported: '성공적으로 내보내졌습니다',
imported: '성공적으로 가져왔습니다'
},
// 키보드 단축키
keyboard: {
navigation: '키보드 내비게이션:',
shortcuts: {
pageUp: '한 페이지 위로 스크롤',
pageDown: '한 페이지 아래로 스크롤',
home: '맨 위로 이동',
end: '맨 아래로 이동',
bulkMode: '일괄 모드 전환',
search: '검색 포커스',
escape: '모달/패널 닫기'
}
},
// 초기화
initialization: {
title: 'LoRA 매니저 초기화',
message: 'LoRA 캐시를 스캔하고 구축중입니다. 몇 분 정도 걸릴 수 있습니다...',
steps: {
scanning: '모델 파일 스캔 중...',
processing: '메타데이터 처리 중...',
building: '캐시 구축 중...',
finalizing: '마무리 중...'
}
},
// 툴팁 및 도움말 텍스트
tooltips: {
refresh: '모델 목록 새로고침',
bulkOperations: '여러 모델을 선택하여 일괄 작업',
favorites: '즐겨찾기 모델만 표시',
duplicates: '중복 모델 찾기 및 관리',
search: '이름, 태그 또는 기타 기준으로 모델 검색',
filter: '다양한 기준으로 모델 필터링',
sort: '다른 속성으로 모델 정렬',
backToTop: '페이지 맨 위로 스크롤'
}
};

View File

@@ -1,397 +0,0 @@
/**
* Russian (ru) translations for LoRA Manager
*/
export const ru = {
// Общие термины, используемые в приложении
common: {
// Операции с файлами
file: 'Файл',
folder: 'Папка',
name: 'Имя',
size: 'Размер',
date: 'Дата',
type: 'Тип',
path: 'Путь',
// Размеры файлов
fileSize: {
zero: '0 Байт',
bytes: 'Байт',
kb: 'КБ',
mb: 'МБ',
gb: 'ГБ',
tb: 'ТБ'
},
// Действия
actions: {
save: 'Сохранить',
cancel: 'Отмена',
delete: 'Удалить',
edit: 'Редактировать',
copy: 'Копировать',
move: 'Переместить',
refresh: 'Обновить',
download: 'Скачать',
upload: 'Загрузить',
search: 'Поиск',
filter: 'Фильтр',
sort: 'Сортировка',
select: 'Выбрать',
selectAll: 'Выбрать все',
deselectAll: 'Отменить выбор',
confirm: 'Подтвердить',
close: 'Закрыть',
back: 'Назад',
next: 'Далее',
previous: 'Предыдущий',
view: 'Просмотр',
preview: 'Предпросмотр',
details: 'Детали',
settings: 'Настройки',
help: 'Помощь',
about: 'О программе'
},
// Настройки языка
language: {
current: 'Язык',
select: 'Выберите язык',
select_help: 'Выберите предпочитаемый язык интерфейса',
english: 'Английский',
chinese_simplified: 'Китайский (упрощенный)',
chinese_traditional: 'Китайский (традиционный)',
russian: 'Русский',
german: 'Немецкий',
japanese: 'Японский',
korean: 'Корейский',
french: 'Французский',
spanish: 'Испанский'
},
// Сообщения о состоянии
status: {
loading: 'Загрузка...',
saving: 'Сохранение...',
saved: 'Сохранено',
error: 'Ошибка',
success: 'Успешно',
warning: 'Предупреждение',
info: 'Информация',
processing: 'Обработка...',
completed: 'Завершено',
failed: 'Не удалось',
cancelled: 'Отменено',
pending: 'Ожидание',
ready: 'Готово'
}
},
// Заголовок и навигация
header: {
appTitle: 'LoRA Менеджер',
navigation: {
loras: 'LoRA',
recipes: 'Рецепты',
checkpoints: 'Чекпоинты',
embeddings: 'Эмбеддинги',
statistics: 'Статистика'
},
search: {
placeholder: 'Поиск...',
placeholders: {
loras: 'Поиск LoRA...',
recipes: 'Поиск рецептов...',
checkpoints: 'Поиск чекпоинтов...',
embeddings: 'Поиск эмбеддингов...'
},
options: 'Опции поиска',
searchIn: 'Искать в:',
notAvailable: 'Поиск недоступен на странице статистики',
filters: {
filename: 'Имя файла',
modelname: 'Имя модели',
tags: 'Теги',
creator: 'Создатель',
title: 'Название рецепта',
loraName: 'Имя файла LoRA',
loraModel: 'Имя модели LoRA'
}
},
filter: {
title: 'Фильтр моделей',
baseModel: 'Базовая модель',
modelTags: 'Теги (топ 20)',
clearAll: 'Очистить все фильтры'
},
theme: {
toggle: 'Переключить тему',
switchToLight: 'Переключить на светлую тему',
switchToDark: 'Переключить на тёмную тему',
switchToAuto: 'Переключить на автоматическую тему'
}
},
// Страница LoRA
loras: {
title: 'LoRA Модели',
controls: {
sort: {
title: 'Сортировать модели по...',
name: 'Имя',
nameAsc: 'A - Z',
nameDesc: 'Z - A',
date: 'Дата добавления',
dateDesc: 'Новые',
dateAsc: 'Старые',
size: 'Размер файла',
sizeDesc: 'Большие',
sizeAsc: 'Маленькие'
},
refresh: {
title: 'Обновить список моделей',
quick: 'Быстрое обновление (инкрементальное)',
full: 'Полная перестройка (полная)'
},
fetch: 'Получить с Civitai',
download: 'Скачать по URL',
bulk: 'Массовые операции',
duplicates: 'Найти дубликаты',
favorites: 'Показать только избранные'
},
bulkOperations: {
title: 'Массовые операции',
selected: 'Выбрано {count}',
selectAll: 'Выбрать все на текущей странице',
deselectAll: 'Отменить выбор всех',
actions: {
move: 'Переместить выбранные',
delete: 'Удалить выбранные',
setRating: 'Установить рейтинг контента',
export: 'Экспортировать выбранные'
}
},
card: {
actions: {
copyTriggerWords: 'Копировать триггерные слова',
copyLoraName: 'Копировать имя LoRA',
sendToWorkflow: 'Отправить в рабочий процесс',
sendToWorkflowAppend: 'Отправить в рабочий процесс (добавить)',
sendToWorkflowReplace: 'Отправить в рабочий процесс (заменить)',
openExamples: 'Открыть папку с примерами',
downloadExamples: 'Скачать примеры изображений',
replacePreview: 'Заменить превью',
setContentRating: 'Установить рейтинг контента',
moveToFolder: 'Переместить в папку',
excludeModel: 'Исключить модель',
deleteModel: 'Удалить модель'
},
modal: {
title: 'Детали LoRA',
tabs: {
examples: 'Примеры',
description: 'Описание модели',
recipes: 'Рецепты'
},
info: {
filename: 'Имя файла',
modelName: 'Имя модели',
baseModel: 'Базовая модель',
fileSize: 'Размер файла',
dateAdded: 'Дата добавления',
triggerWords: 'Триггерные слова',
description: 'Описание',
tags: 'Теги',
rating: 'Рейтинг',
downloads: 'Скачивания',
likes: 'Лайки',
version: 'Версия'
},
actions: {
copyTriggerWords: 'Копировать триггерные слова',
copyLoraName: 'Копировать имя LoRA',
sendToWorkflow: 'Отправить в рабочий процесс',
viewOnCivitai: 'Просмотреть на Civitai',
downloadExamples: 'Скачать примеры изображений'
}
}
}
},
// Страница рецептов
recipes: {
title: 'LoRA Рецепты',
controls: {
import: 'Импортировать рецепт',
create: 'Создать рецепт',
export: 'Экспортировать выбранные',
downloadMissing: 'Скачать отсутствующие LoRA'
},
card: {
author: 'Автор',
loras: '{count} LoRA',
tags: 'Теги',
actions: {
sendToWorkflow: 'Отправить в рабочий процесс',
edit: 'Редактировать рецепт',
duplicate: 'Дублировать рецепт',
export: 'Экспортировать рецепт',
delete: 'Удалить рецепт'
}
}
},
// Страница чекпоинтов
checkpoints: {
title: 'Чекпоинты',
info: {
filename: 'Имя файла',
modelName: 'Имя модели',
baseModel: 'Базовая модель',
fileSize: 'Размер файла',
dateAdded: 'Дата добавления'
}
},
// Страница эмбеддингов
embeddings: {
title: 'Эмбеддинги',
info: {
filename: 'Имя файла',
modelName: 'Имя модели',
triggerWords: 'Триггерные слова',
fileSize: 'Размер файла',
dateAdded: 'Дата добавления'
}
},
// Страница статистики
statistics: {
title: 'Статистика',
overview: {
title: 'Обзор',
totalModels: 'Всего моделей',
totalSize: 'Общий размер',
avgFileSize: 'Средний размер файла',
newestModel: 'Новейшая модель'
},
charts: {
modelsByBaseModel: 'По базовым моделям',
modelsByMonth: 'По месяцам',
fileSizeDistribution: 'Распределение размеров файлов',
topTags: 'Популярные теги'
}
},
// Модальные окна
modals: {
delete: {
title: 'Подтвердить удаление',
message: 'Вы уверены, что хотите удалить эту модель? Это действие нельзя отменить.',
confirm: 'Удалить',
cancel: 'Отмена'
},
exclude: {
title: 'Исключить модель',
message: 'Вы уверены, что хотите исключить эту модель из библиотеки?',
confirm: 'Исключить',
cancel: 'Отмена'
},
download: {
title: 'Скачать модель',
url: 'URL модели',
placeholder: 'Введите URL модели Civitai...',
download: 'Скачать',
cancel: 'Отмена'
},
move: {
title: 'Переместить модель',
selectFolder: 'Выберите папку назначения',
createFolder: 'Создать новую папку',
folderName: 'Имя папки',
move: 'Переместить',
cancel: 'Отмена'
},
contentRating: {
title: 'Установить рейтинг контента',
current: 'Текущий',
levels: {
pg: 'Для всех',
pg13: 'С 13 лет',
r: 'Ограниченный',
x: 'Для взрослых',
xxx: 'Эротический'
}
}
},
// Сообщения об ошибках
errors: {
general: 'Произошла ошибка',
networkError: 'Ошибка сети. Проверьте подключение.',
serverError: 'Ошибка сервера. Попробуйте позже.',
fileNotFound: 'Файл не найден',
invalidFile: 'Неверный формат файла',
uploadFailed: 'Загрузка не удалась',
downloadFailed: 'Скачивание не удалось',
saveFailed: 'Сохранение не удалось',
loadFailed: 'Загрузка не удалась',
deleteFailed: 'Удаление не удалось',
moveFailed: 'Перемещение не удалось',
copyFailed: 'Копирование не удалось',
fetchFailed: 'Не удалось получить данные с Civitai',
invalidUrl: 'Неверный формат URL',
missingPermissions: 'Недостаточно прав'
},
// Сообщения об успехе
success: {
saved: 'Успешно сохранено',
deleted: 'Успешно удалено',
moved: 'Успешно перемещено',
copied: 'Успешно скопировано',
downloaded: 'Успешно скачано',
uploaded: 'Успешно загружено',
refreshed: 'Успешно обновлено',
exported: 'Успешно экспортировано',
imported: 'Успешно импортировано'
},
// Горячие клавиши
keyboard: {
navigation: 'Навигация с клавиатуры:',
shortcuts: {
pageUp: 'Прокрутить вверх на одну страницу',
pageDown: 'Прокрутить вниз на одну страницу',
home: 'Перейти к началу',
end: 'Перейти к концу',
bulkMode: 'Переключить массовый режим',
search: 'Фокус на поиске',
escape: 'Закрыть модальное окно/панель'
}
},
// Инициализация
initialization: {
title: 'Инициализация LoRA Менеджера',
message: 'Сканирование и построение кэша LoRA. Это может занять несколько минут...',
steps: {
scanning: 'Сканирование файлов моделей...',
processing: 'Обработка метаданных...',
building: 'Построение кэша...',
finalizing: 'Завершение...'
}
},
// Подсказки и справочный текст
tooltips: {
refresh: 'Обновить список моделей',
bulkOperations: 'Выбрать несколько моделей для массовых операций',
favorites: 'Показать только избранные модели',
duplicates: 'Найти и управлять дублирующимися моделями',
search: 'Поиск моделей по имени, тегам или другим критериям',
filter: 'Фильтровать модели по различным критериям',
sort: 'Сортировать модели по разным атрибутам',
backToTop: 'Прокрутить обратно к верху страницы'
}
};

View File

@@ -1,415 +0,0 @@
/**
* Simplified Chinese (zh-CN) translations for LoRA Manager
*/
export const zhCN = {
// 应用中使用的通用术语
common: {
// 文件操作
file: '文件',
folder: '文件夹',
name: '名称',
size: '大小',
date: '日期',
type: '类型',
path: '路径',
// 文件大小
fileSize: {
zero: '0 字节',
bytes: '字节',
kb: 'KB',
mb: 'MB',
gb: 'GB',
tb: 'TB'
},
// 操作
actions: {
save: '保存',
cancel: '取消',
delete: '删除',
edit: '编辑',
copy: '复制',
move: '移动',
refresh: '刷新',
download: '下载',
upload: '上传',
search: '搜索',
filter: '筛选',
sort: '排序',
select: '选择',
selectAll: '全选',
deselectAll: '取消全选',
confirm: '确认',
close: '关闭',
back: '返回',
next: '下一步',
previous: '上一步',
view: '查看',
preview: '预览',
details: '详情',
settings: '设置',
help: '帮助',
about: '关于'
},
// 语言设置
language: {
current: '语言',
select: '选择语言',
select_help: '选择您偏好的界面语言',
english: '英语',
chinese_simplified: '中文(简体)',
chinese_traditional: '中文(繁体)',
russian: '俄语',
german: '德语',
japanese: '日语',
korean: '韩语',
french: '法语',
spanish: '西班牙语'
},
// 状态信息
status: {
loading: '加载中...',
saving: '保存中...',
saved: '已保存',
error: '错误',
success: '成功',
warning: '警告',
info: '信息',
processing: '处理中...',
completed: '已完成',
failed: '失败',
cancelled: '已取消',
pending: '等待中',
ready: '就绪'
}
},
// 头部和导航
header: {
appTitle: 'LoRA 管理器',
navigation: {
loras: 'LoRA',
recipes: '配方',
checkpoints: 'Checkpoint',
embeddings: 'Embedding',
statistics: '统计'
},
search: {
placeholder: '搜索...',
placeholders: {
loras: '搜索 LoRA...',
recipes: '搜索配方...',
checkpoints: '搜索Checkpoint...',
embeddings: '搜索 Embedding...'
},
options: '搜索选项',
searchIn: '搜索范围:',
notAvailable: '统计页面不支持搜索',
filters: {
filename: '文件名',
modelname: '模型名称',
tags: '标签',
creator: '创作者',
title: '配方标题',
loraName: 'LoRA 文件名',
loraModel: 'LoRA 模型名称'
}
},
filter: {
title: '筛选模型',
baseModel: '基础模型',
modelTags: '标签前20个',
clearAll: '清除所有筛选'
},
theme: {
toggle: '切换主题',
switchToLight: '切换到浅色主题',
switchToDark: '切换到深色主题',
switchToAuto: '切换到自动主题'
}
},
// LoRA 页面
loras: {
title: 'LoRA',
controls: {
sort: {
title: '排序方式...',
name: '名称',
nameAsc: 'A - Z',
nameDesc: 'Z - A',
date: '添加日期',
dateDesc: '最新',
dateAsc: '最旧',
size: '文件大小',
sizeDesc: '最大',
sizeAsc: '最小'
},
refresh: {
title: '刷新模型列表',
quick: '快速刷新(增量)',
full: '完全重建(完整)'
},
fetch: '从 Civitai 获取',
download: '从 URL 下载',
bulk: '批量操作',
duplicates: '查找重复项',
favorites: '仅显示收藏'
},
bulkOperations: {
title: '批量操作',
selected: '已选择{count}项',
sendToWorkflow: '发送到工作流',
copyAll: '复制LoRA语法',
refreshAll: '刷新元数据',
moveAll: '移动',
deleteAll: '删除',
clear: '清除选择'
},
contextMenu: {
refreshMetadata: '刷新 Civitai 数据',
relinkCivitai: '重新链接到 Civitai',
copySyntax: '复制 LoRA 语法',
sendToWorkflowAppend: '发送到工作流(追加)',
sendToWorkflowReplace: '发送到工作流(替换)',
openExamples: '打开示例文件夹',
downloadExamples: '下载示例图片',
replacePreview: '替换预览图',
setContentRating: '设置内容评级',
moveToFolder: '移动到文件夹',
excludeModel: '排除模型',
deleteModel: '删除模型'
},
modal: {
title: 'LoRA 详情',
tabs: {
examples: '示例',
description: '模型描述',
recipes: '配方'
},
info: {
filename: '文件名',
modelName: '模型名称',
baseModel: '基础模型',
fileSize: '文件大小',
dateAdded: '添加日期',
triggerWords: '触发词',
description: '描述',
tags: '标签',
rating: '评分',
downloads: '下载量',
likes: '点赞数',
version: '版本'
},
actions: {
copyTriggerWords: '复制触发词',
copyLoraName: '复制 LoRA 名称',
sendToWorkflow: '发送到工作流',
viewOnCivitai: '在 Civitai 上查看',
downloadExamples: '下载示例图片'
}
}
},
// 配方页面
recipes: {
title: 'LoRA 配方',
controls: {
import: '导入配方',
create: '创建配方',
export: '导出选中',
downloadMissing: '下载缺失的 LoRA'
},
card: {
author: '作者',
loras: '{count} 个 LoRA',
tags: '标签',
actions: {
sendToWorkflow: '发送到工作流',
edit: '编辑配方',
duplicate: '复制配方',
export: '导出配方',
delete: '删除配方'
}
}
},
// Checkpoint页面
checkpoints: {
title: 'Checkpoint',
info: {
filename: '文件名',
modelName: '模型名称',
baseModel: '基础模型',
fileSize: '文件大小',
dateAdded: '添加日期'
}
},
// 嵌入模型页面
embeddings: {
title: 'Embedding',
info: {
filename: '文件名',
modelName: '模型名称',
triggerWords: '触发词',
fileSize: '文件大小',
dateAdded: '添加日期'
}
},
// 统计页面
statistics: {
title: '统计信息',
overview: {
title: '概览',
totalLoras: 'LoRA 总数',
totalCheckpoints: 'Checkpoint总数',
totalEmbeddings: 'Embedding 总数',
totalSize: '总大小',
favoriteModels: '收藏模型'
},
charts: {
modelsByType: '按类型统计模型',
modelsByBaseModel: '按基础模型统计',
modelsBySize: '按文件大小统计',
modelsAddedOverTime: '模型添加时间分布'
}
},
// 模态框和对话框
modals: {
delete: {
title: '确认删除',
message: '确定要删除这个模型吗?',
warningMessage: '此操作无法撤销。',
confirm: '删除',
cancel: '取消'
},
exclude: {
title: '排除模型',
message: '确定要从库中排除这个模型吗?',
confirm: '排除',
cancel: '取消'
},
download: {
title: '下载模型',
url: '模型 URL',
placeholder: '输入 Civitai 模型 URL...',
download: '下载',
cancel: '取消'
},
move: {
title: '移动模型',
selectFolder: '选择目标文件夹',
createFolder: '创建新文件夹',
folderName: '文件夹名称',
move: '移动',
cancel: '取消'
},
contentRating: {
title: '设置内容评级',
current: '当前',
levels: {
pg: '普通级',
pg13: '辅导级',
r: '限制级',
x: '成人级',
xxx: '重口级'
}
}
},
// 错误信息
errors: {
general: '发生错误',
networkError: '网络错误,请检查您的连接。',
serverError: '服务器错误,请稍后重试。',
fileNotFound: '文件未找到',
invalidFile: '无效的文件格式',
uploadFailed: '上传失败',
downloadFailed: '下载失败',
saveFailed: '保存失败',
loadFailed: '加载失败',
deleteFailed: '删除失败',
moveFailed: '移动失败',
copyFailed: '复制失败',
fetchFailed: '从 Civitai 获取数据失败',
invalidUrl: '无效的 URL 格式',
missingPermissions: '权限不足'
},
// 成功信息
success: {
saved: '保存成功',
deleted: '删除成功',
moved: '移动成功',
copied: '复制成功',
downloaded: '下载成功',
uploaded: '上传成功',
refreshed: '刷新成功',
exported: '导出成功',
imported: '导入成功'
},
// 键盘快捷键
keyboard: {
navigation: '键盘导航:',
shortcuts: {
pageUp: '向上滚动一页',
pageDown: '向下滚动一页',
home: '跳转到顶部',
end: '跳转到底部',
bulkMode: '切换批量模式',
search: '聚焦搜索框',
escape: '关闭模态框/面板'
}
},
// 初始化
initialization: {
title: '初始化 LoRA 管理器',
message: '正在扫描并构建 LoRA 缓存,这可能需要几分钟时间...',
loras: {
title: '初始化 LoRA 管理器',
message: '正在扫描并构建 LoRA 缓存,这可能需要几分钟时间...'
},
checkpoints: {
title: '初始化Checkpoint管理器',
message: '正在扫描并构建Checkpoint缓存这可能需要几分钟时间...'
},
embeddings: {
title: '初始化 Embedding 管理器',
message: '正在扫描并构建 Embedding 缓存,这可能需要几分钟时间...'
},
recipes: {
title: '初始化配方管理器',
message: '正在加载和处理配方,这可能需要几分钟时间...'
},
statistics: {
title: '初始化统计信息',
message: '正在处理模型数据以生成统计信息,这可能需要几分钟时间...'
},
steps: {
scanning: '扫描模型文件...',
processing: '处理元数据...',
building: '构建缓存...',
finalizing: '完成中...'
}
},
// 工具提示和帮助文本
tooltips: {
refresh: '刷新模型列表',
bulkOperations: '选择多个模型进行批量操作',
favorites: '仅显示收藏的模型',
duplicates: '查找和管理重复的模型',
search: '按名称、标签或其他条件搜索模型',
filter: '按各种条件筛选模型',
sort: '按不同属性排序模型',
backToTop: '滚动回页面顶部'
}
};

View File

@@ -1,397 +0,0 @@
/**
* Traditional Chinese (zh-TW) translations for LoRA Manager
*/
export const zhTW = {
// 應用中使用的通用術語
common: {
// 檔案操作
file: '檔案',
folder: '資料夾',
name: '名稱',
size: '大小',
date: '日期',
type: '類型',
path: '路徑',
// 檔案大小
fileSize: {
zero: '0 位元組',
bytes: '位元組',
kb: 'KB',
mb: 'MB',
gb: 'GB',
tb: 'TB'
},
// 操作
actions: {
save: '儲存',
cancel: '取消',
delete: '刪除',
edit: '編輯',
copy: '複製',
move: '移動',
refresh: '重新整理',
download: '下載',
upload: '上傳',
search: '搜尋',
filter: '篩選',
sort: '排序',
select: '選擇',
selectAll: '全選',
deselectAll: '取消全選',
confirm: '確認',
close: '關閉',
back: '返回',
next: '下一步',
previous: '上一步',
view: '檢視',
preview: '預覽',
details: '詳情',
settings: '設定',
help: '說明',
about: '關於'
},
// 語言設定
language: {
current: '語言',
select: '選擇語言',
select_help: '選擇您偏好的介面語言',
english: '英語',
chinese_simplified: '中文(簡體)',
chinese_traditional: '中文(繁體)',
russian: '俄語',
german: '德語',
japanese: '日語',
korean: '韓語',
french: '法語',
spanish: '西班牙語'
},
// 狀態資訊
status: {
loading: '載入中...',
saving: '儲存中...',
saved: '已儲存',
error: '錯誤',
success: '成功',
warning: '警告',
info: '資訊',
processing: '處理中...',
completed: '已完成',
failed: '失敗',
cancelled: '已取消',
pending: '等待中',
ready: '就緒'
}
},
// 標題列和導覽
header: {
appTitle: 'LoRA 管理器',
navigation: {
loras: 'LoRA',
recipes: '配方',
checkpoints: 'Checkpoint',
embeddings: 'Embedding',
statistics: '統計'
},
search: {
placeholder: '搜尋...',
placeholders: {
loras: '搜尋 LoRA...',
recipes: '搜尋配方...',
checkpoints: '搜尋Checkpoint...',
embeddings: '搜尋 Embedding...'
},
options: '搜尋選項',
searchIn: '搜尋範圍:',
notAvailable: '統計頁面不支援搜尋',
filters: {
filename: '檔案名稱',
modelname: '模型名稱',
tags: '標籤',
creator: '創作者',
title: '配方標題',
loraName: 'LoRA 檔案名稱',
loraModel: 'LoRA 模型名稱'
}
},
filter: {
title: '篩選模型',
baseModel: '基礎模型',
modelTags: '標籤前20個',
clearAll: '清除所有篩選'
},
theme: {
toggle: '切換主題',
switchToLight: '切換到淺色主題',
switchToDark: '切換到深色主題',
switchToAuto: '切換到自動主題'
}
},
// LoRA 頁面
loras: {
title: 'LoRA 模型',
controls: {
sort: {
title: '排序方式...',
name: '名稱',
nameAsc: 'A - Z',
nameDesc: 'Z - A',
date: '新增日期',
dateDesc: '最新',
dateAsc: '最舊',
size: '檔案大小',
sizeDesc: '最大',
sizeAsc: '最小'
},
refresh: {
title: '重新整理模型清單',
quick: '快速重新整理(增量)',
full: '完整重建(完整)'
},
fetch: '從 Civitai 獲取',
download: '從 URL 下載',
bulk: '批次操作',
duplicates: '尋找重複項',
favorites: '僅顯示收藏'
},
bulkOperations: {
title: '批次操作',
selected: '已選擇 {count} 個',
selectAll: '選擇所有當前頁面',
deselectAll: '取消選擇所有',
actions: {
move: '移動選中項目',
delete: '刪除選中項目',
setRating: '設定內容評級',
export: '匯出選中項目'
}
},
card: {
actions: {
copyTriggerWords: '複製觸發詞',
copyLoraName: '複製 LoRA 名稱',
sendToWorkflow: '傳送到工作流程',
sendToWorkflowAppend: '傳送到工作流程(附加)',
sendToWorkflowReplace: '傳送到工作流程(替換)',
openExamples: '開啟範例資料夾',
downloadExamples: '下載範例圖片',
replacePreview: '替換預覽圖',
setContentRating: '設定內容評級',
moveToFolder: '移動到資料夾',
excludeModel: '排除模型',
deleteModel: '刪除模型'
},
modal: {
title: 'LoRA 詳情',
tabs: {
examples: '範例',
description: '模型描述',
recipes: '配方'
},
info: {
filename: '檔案名稱',
modelName: '模型名稱',
baseModel: '基礎模型',
fileSize: '檔案大小',
dateAdded: '新增日期',
triggerWords: '觸發詞',
description: '描述',
tags: '標籤',
rating: '評級',
downloads: '下載次數',
likes: '按讚數',
version: '版本'
},
actions: {
copyTriggerWords: '複製觸發詞',
copyLoraName: '複製 LoRA 名稱',
sendToWorkflow: '傳送到工作流程',
viewOnCivitai: '在 Civitai 檢視',
downloadExamples: '下載範例圖片'
}
}
}
},
// 配方頁面
recipes: {
title: 'LoRA 配方',
controls: {
import: '匯入配方',
create: '建立配方',
export: '匯出選中項目',
downloadMissing: '下載缺少的 LoRA'
},
card: {
author: '作者',
loras: '{count} 個 LoRA',
tags: '標籤',
actions: {
sendToWorkflow: '傳送到工作流程',
edit: '編輯配方',
duplicate: '複製配方',
export: '匯出配方',
delete: '刪除配方'
}
}
},
// Checkpoint頁面
checkpoints: {
title: 'Checkpoint',
info: {
filename: '檔案名稱',
modelName: '模型名稱',
baseModel: '基礎模型',
fileSize: '檔案大小',
dateAdded: '新增日期'
}
},
// Embedding 頁面
embeddings: {
title: 'Embedding 模型',
info: {
filename: '檔案名稱',
modelName: '模型名稱',
triggerWords: '觸發詞',
fileSize: '檔案大小',
dateAdded: '新增日期'
}
},
// 統計頁面
statistics: {
title: '統計',
overview: {
title: '概覽',
totalModels: '總模型數',
totalSize: '總大小',
avgFileSize: '平均檔案大小',
newestModel: '最新模型'
},
charts: {
modelsByBaseModel: '按基礎模型分類',
modelsByMonth: '按月份分類',
fileSizeDistribution: '檔案大小分佈',
topTags: '熱門標籤'
}
},
// 模態對話框
modals: {
delete: {
title: '確認刪除',
message: '確定要刪除這個模型嗎?此操作無法復原。',
confirm: '刪除',
cancel: '取消'
},
exclude: {
title: '排除模型',
message: '確定要從程式庫中排除這個模型嗎?',
confirm: '排除',
cancel: '取消'
},
download: {
title: '下載模型',
url: '模型 URL',
placeholder: '輸入 Civitai 模型 URL...',
download: '下載',
cancel: '取消'
},
move: {
title: '移動模型',
selectFolder: '選擇目標資料夾',
createFolder: '建立新資料夾',
folderName: '資料夾名稱',
move: '移動',
cancel: '取消'
},
contentRating: {
title: '設定內容評級',
current: '目前',
levels: {
pg: '普通級',
pg13: '輔導級',
r: '限制級',
x: '成人級',
xxx: '重口級'
}
}
},
// 錯誤訊息
errors: {
general: '發生錯誤',
networkError: '網路錯誤。請檢查您的連線。',
serverError: '伺服器錯誤。請稍後再試。',
fileNotFound: '找不到檔案',
invalidFile: '無效的檔案格式',
uploadFailed: '上傳失敗',
downloadFailed: '下載失敗',
saveFailed: '儲存失敗',
loadFailed: '載入失敗',
deleteFailed: '刪除失敗',
moveFailed: '移動失敗',
copyFailed: '複製失敗',
fetchFailed: '無法從 Civitai 獲取資料',
invalidUrl: '無效的 URL 格式',
missingPermissions: '權限不足'
},
// 成功訊息
success: {
saved: '儲存成功',
deleted: '刪除成功',
moved: '移動成功',
copied: '複製成功',
downloaded: '下載成功',
uploaded: '上傳成功',
refreshed: '重新整理成功',
exported: '匯出成功',
imported: '匯入成功'
},
// 鍵盤快速鍵
keyboard: {
navigation: '鍵盤導覽:',
shortcuts: {
pageUp: '向上捲動一頁',
pageDown: '向下捲動一頁',
home: '跳轉到頂部',
end: '跳轉到底部',
bulkMode: '切換批次模式',
search: '聚焦搜尋框',
escape: '關閉模態框/面板'
}
},
// 初始化
initialization: {
title: '初始化 LoRA 管理器',
message: '正在掃描並建構 LoRA 快取,這可能需要幾分鐘時間...',
steps: {
scanning: '掃描模型檔案...',
processing: '處理中繼資料...',
building: '建構快取...',
finalizing: '完成中...'
}
},
// 工具提示和說明文字
tooltips: {
refresh: '重新整理模型清單',
bulkOperations: '選擇多個模型進行批次操作',
favorites: '僅顯示收藏的模型',
duplicates: '尋找並管理重複的模型',
search: '按名稱、標籤或其他條件搜尋模型',
filter: '按各種條件篩選模型',
sort: '按不同屬性排序模型',
backToTop: '捲動回頁面頂部'
}
};

View File

@@ -5,7 +5,6 @@ import { LoraContextMenu } from './components/ContextMenu/index.js';
import { createPageControls } from './components/controls/index.js';
import { confirmDelete, closeDeleteModal, confirmExclude, closeExcludeModal } from './utils/modalUtils.js';
import { ModelDuplicatesManager } from './components/ModelDuplicatesManager.js';
import { initializePageI18n } from './utils/i18nHelpers.js';
// Initialize the LoRA page
class LoraPageManager {
@@ -46,9 +45,6 @@ class LoraPageManager {
// Initialize common page features (virtual scroll)
appCore.initializePageFeatures();
// Initialize i18n for the page
initializePageI18n();
}
}

View File

@@ -2,7 +2,7 @@
<html>
<head>
<title>{% block title %}LoRA Manager{% endblock %}</title>
<title>{% block title %}{{ t('header.appTitle') }}{% endblock %}</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="/loras_static/css/style.css">
{% block page_css %}{% endblock %}
@@ -77,7 +77,7 @@
{% block additional_components %}{% endblock %}
<!-- Add back-to-top button here -->
<button id="backToTopBtn" class="back-to-top" title="Back to top">
<button id="backToTopBtn" class="back-to-top" title="{{ t('common.actions.backToTop') }}">
<i class="fas fa-chevron-up"></i>
</button>

View File

@@ -1,30 +1,30 @@
{% extends "base.html" %}
{% block title %}Checkpoints Manager{% endblock %}
{% block title %}{{ t('checkpoints.title') }}{% endblock %}
{% block page_id %}checkpoints{% endblock %}
{% block preload %}
<link rel="preload" href="/loras_static/js/checkpoints.js" as="script" crossorigin="anonymous">
{% endblock %}
{% block init_title %}Initializing Checkpoints Manager{% endblock %}
{% block init_message %}Scanning and building checkpoints cache. This may take a few moments...{% endblock %}
{% block init_title %}{{ t('initialization.checkpoints.title') }}{% endblock %}
{% block init_message %}{{ t('initialization.checkpoints.message') }}{% endblock %}
{% block init_check_url %}/api/checkpoints/list?page=1&page_size=1{% endblock %}
{% block additional_components %}
<div id="checkpointContextMenu" class="context-menu" style="display: none;">
<div class="context-menu-item" data-action="refresh-metadata"><i class="fas fa-sync"></i> Refresh Civitai Data</div>
<div class="context-menu-item" data-action="relink-civitai"><i class="fas fa-link"></i> Re-link to Civitai</div>
<div class="context-menu-item" data-action="copyname"><i class="fas fa-copy"></i> Copy Model Filename</div>
<div class="context-menu-item" data-action="preview"><i class="fas fa-folder-open"></i> Open Examples Folder</div>
<div class="context-menu-item" data-action="download-examples"><i class="fas fa-download"></i> Download Example Images</div>
<div class="context-menu-item" data-action="replace-preview"><i class="fas fa-image"></i> Replace Preview</div>
<div class="context-menu-item" data-action="set-nsfw"><i class="fas fa-exclamation-triangle"></i> Set Content Rating</div>
<div class="context-menu-item" data-action="refresh-metadata"><i class="fas fa-sync"></i> {{ t('contextMenu.refreshMetadata') }}</div>
<div class="context-menu-item" data-action="relink-civitai"><i class="fas fa-link"></i> {{ t('contextMenu.relinkCivitai') }}</div>
<div class="context-menu-item" data-action="copyname"><i class="fas fa-copy"></i> {{ t('contextMenu.copyFilename') }}</div>
<div class="context-menu-item" data-action="preview"><i class="fas fa-folder-open"></i> {{ t('contextMenu.openExamplesFolder') }}</div>
<div class="context-menu-item" data-action="download-examples"><i class="fas fa-download"></i> {{ t('contextMenu.downloadExamples') }}</div>
<div class="context-menu-item" data-action="replace-preview"><i class="fas fa-image"></i> {{ t('contextMenu.replacePreview') }}</div>
<div class="context-menu-item" data-action="set-nsfw"><i class="fas fa-exclamation-triangle"></i> {{ t('contextMenu.setContentRating') }}</div>
<div class="context-menu-separator"></div>
<div class="context-menu-item" data-action="move"><i class="fas fa-folder-open"></i> Move to Folder</div>
<div class="context-menu-item" data-action="exclude"><i class="fas fa-eye-slash"></i> Exclude Model</div>
<div class="context-menu-item delete-item" data-action="delete"><i class="fas fa-trash"></i> Delete Model</div>
<div class="context-menu-item" data-action="move"><i class="fas fa-folder-open"></i> {{ t('contextMenu.moveToFolder') }}</div>
<div class="context-menu-item" data-action="exclude"><i class="fas fa-eye-slash"></i> {{ t('contextMenu.excludeModel') }}</div>
<div class="context-menu-item delete-item" data-action="delete"><i class="fas fa-trash"></i> {{ t('contextMenu.deleteModel') }}</div>
</div>
{% endblock %}

View File

@@ -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>

View File

@@ -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>

View File

@@ -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>

View File

@@ -3,18 +3,18 @@
<div class="modal-content">
<div class="modal-header">
<button class="close" id="closeDownloadModal">&times;</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>

View File

@@ -1,30 +1,30 @@
{% extends "base.html" %}
{% block title %}Embeddings Manager{% endblock %}
{% block title %}{{ t('embeddings.title') }}{% endblock %}
{% block page_id %}embeddings{% endblock %}
{% block preload %}
<link rel="preload" href="/loras_static/js/embeddings.js" as="script" crossorigin="anonymous">
{% endblock %}
{% block init_title %}Initializing Embeddings Manager{% endblock %}
{% block init_message %}Scanning and building embeddings cache. This may take a few moments...{% endblock %}
{% block init_title %}{{ t('initialization.embeddings.title') }}{% endblock %}
{% block init_message %}{{ t('initialization.embeddings.message') }}{% endblock %}
{% block init_check_url %}/api/embeddings/list?page=1&page_size=1{% endblock %}
{% block additional_components %}
<div id="embeddingContextMenu" class="context-menu" style="display: none;">
<div class="context-menu-item" data-action="refresh-metadata"><i class="fas fa-sync"></i> Refresh Civitai Data</div>
<div class="context-menu-item" data-action="relink-civitai"><i class="fas fa-link"></i> Re-link to Civitai</div>
<div class="context-menu-item" data-action="copyname"><i class="fas fa-copy"></i> Copy Model Filename</div>
<div class="context-menu-item" data-action="preview"><i class="fas fa-folder-open"></i> Open Examples Folder</div>
<div class="context-menu-item" data-action="download-examples"><i class="fas fa-download"></i> Download Example Images</div>
<div class="context-menu-item" data-action="replace-preview"><i class="fas fa-image"></i> Replace Preview</div>
<div class="context-menu-item" data-action="set-nsfw"><i class="fas fa-exclamation-triangle"></i> Set Content Rating</div>
<div class="context-menu-item" data-action="refresh-metadata"><i class="fas fa-sync"></i> {{ t('contextMenu.refreshMetadata') }}</div>
<div class="context-menu-item" data-action="relink-civitai"><i class="fas fa-link"></i> {{ t('contextMenu.relinkCivitai') }}</div>
<div class="context-menu-item" data-action="copyname"><i class="fas fa-copy"></i> {{ t('contextMenu.copyFilename') }}</div>
<div class="context-menu-item" data-action="preview"><i class="fas fa-folder-open"></i> {{ t('contextMenu.openExamplesFolder') }}</div>
<div class="context-menu-item" data-action="download-examples"><i class="fas fa-download"></i> {{ t('contextMenu.downloadExamples') }}</div>
<div class="context-menu-item" data-action="replace-preview"><i class="fas fa-image"></i> {{ t('contextMenu.replacePreview') }}</div>
<div class="context-menu-item" data-action="set-nsfw"><i class="fas fa-exclamation-triangle"></i> {{ t('contextMenu.setContentRating') }}</div>
<div class="context-menu-separator"></div>
<div class="context-menu-item" data-action="move"><i class="fas fa-folder-open"></i> Move to Folder</div>
<div class="context-menu-item" data-action="exclude"><i class="fas fa-eye-slash"></i> Exclude Model</div>
<div class="context-menu-item delete-item" data-action="delete"><i class="fas fa-trash"></i> Delete Model</div>
<div class="context-menu-item" data-action="move"><i class="fas fa-folder-open"></i> {{ t('contextMenu.moveToFolder') }}</div>
<div class="context-menu-item" data-action="exclude"><i class="fas fa-eye-slash"></i> {{ t('contextMenu.excludeModel') }}</div>
<div class="context-menu-item delete-item" data-action="delete"><i class="fas fa-trash"></i> {{ t('contextMenu.deleteModel') }}</div>
</div>
{% endblock %}

View File

@@ -1,6 +1,6 @@
{% extends "base.html" %}
{% block title %}LoRA Recipes{% endblock %}
{% block title %}{{ t('recipes.title') }}{% endblock %}
{% block page_id %}recipes{% endblock %}
{% block page_css %}
@@ -19,42 +19,42 @@
<div id="recipeContextMenu" class="context-menu" style="display: none;">
<!-- <div class="context-menu-item" data-action="details"><i class="fas fa-info-circle"></i> View Details</div> -->
<div class="context-menu-item" data-action="share"><i class="fas fa-share-alt"></i> Share Recipe</div>
<div class="context-menu-item" data-action="copy"><i class="fas fa-copy"></i> Copy Recipe Syntax</div>
<div class="context-menu-item" data-action="sendappend"><i class="fas fa-paper-plane"></i> Send to Workflow (Append)</div>
<div class="context-menu-item" data-action="sendreplace"><i class="fas fa-exchange-alt"></i> Send to Workflow (Replace)</div>
<div class="context-menu-item" data-action="viewloras"><i class="fas fa-layer-group"></i> View All LoRAs</div>
<div class="context-menu-item download-missing-item" data-action="download-missing"><i class="fas fa-download"></i> Download Missing LoRAs</div>
<div class="context-menu-item" data-action="share"><i class="fas fa-share-alt"></i> {{ t('contextMenu.shareRecipe') }}</div>
<div class="context-menu-item" data-action="copy"><i class="fas fa-copy"></i> {{ t('contextMenu.copyRecipeSyntax') }}</div>
<div class="context-menu-item" data-action="sendappend"><i class="fas fa-paper-plane"></i> {{ t('contextMenu.sendToWorkflowAppend') }}</div>
<div class="context-menu-item" data-action="sendreplace"><i class="fas fa-exchange-alt"></i> {{ t('contextMenu.sendToWorkflowReplace') }}</div>
<div class="context-menu-item" data-action="viewloras"><i class="fas fa-layer-group"></i> {{ t('contextMenu.viewAllLoras') }}</div>
<div class="context-menu-item download-missing-item" data-action="download-missing"><i class="fas fa-download"></i> {{ t('contextMenu.downloadMissingLoras') }}</div>
<div class="context-menu-item" data-action="set-nsfw">
<i class="fas fa-exclamation-triangle"></i> Set Content Rating
<i class="fas fa-exclamation-triangle"></i> {{ t('contextMenu.setContentRating') }}
</div>
<div class="context-menu-separator"></div>
<div class="context-menu-item delete-item" data-action="delete"><i class="fas fa-trash"></i> Delete Recipe</div>
<div class="context-menu-item delete-item" data-action="delete"><i class="fas fa-trash"></i> {{ t('contextMenu.deleteRecipe') }}</div>
</div>
{% endblock %}
{% block init_title %}Initializing Recipe Manager{% endblock %}
{% block init_message %}Scanning and building recipe cache. This may take a few moments...{% endblock %}
{% block init_title %}{{ t('initialization.recipes.title') }}{% endblock %}
{% block init_message %}{{ t('initialization.recipes.message') }}{% endblock %}
{% block init_check_url %}/api/recipes?page=1&page_size=1{% endblock %}
{% block content %}
<!-- Recipe controls -->
<div class="controls">
<div class="action-buttons">
<div title="Refresh recipe list" class="control-group">
<button onclick="recipeManager.refreshRecipes()"><i class="fas fa-sync"></i> Refresh</button>
<div title="{{ t('recipes.controls.refresh.title') }}" class="control-group">
<button onclick="recipeManager.refreshRecipes()"><i class="fas fa-sync"></i> {{ t('common.actions.refresh') }}</button>
</div>
<div title="Import recipes" class="control-group">
<button onclick="importManager.showImportModal()"><i class="fas fa-file-import"></i> Import</button>
<div title="{{ t('recipes.controls.import.title') }}" class="control-group">
<button onclick="importManager.showImportModal()"><i class="fas fa-file-import"></i> {{ t('recipes.controls.import') }}</button>
</div>
<!-- Add duplicate detection button -->
<div title="Find duplicate recipes" class="control-group">
<button onclick="recipeManager.findDuplicateRecipes()"><i class="fas fa-clone"></i> Duplicates</button>
<div title="{{ t('recipes.controls.duplicates.title') }}" class="control-group">
<button onclick="recipeManager.findDuplicateRecipes()"><i class="fas fa-clone"></i> {{ t('recipes.controls.duplicates') }}</button>
</div>
<!-- Custom filter indicator button (hidden by default) -->
<div id="customFilterIndicator" class="control-group hidden">
<div class="filter-active">
<i class="fas fa-filter"></i> <span id="customFilterText">Filtered by LoRA</span>
<i class="fas fa-filter"></i> <span id="customFilterText">{{ t('recipes.controls.filteredByLora') }}</span>
<i class="fas fa-times-circle clear-filter"></i>
</div>
</div>
@@ -65,13 +65,13 @@
<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>
<span id="duplicatesCount">{{ t('recipes.duplicates.found', count=0) }}</span>
<div class="banner-actions">
<button class="btn-select-latest" onclick="recipeManager.selectLatestDuplicates()">
Keep Latest Versions
{{ t('recipes.duplicates.keepLatest') }}
</button>
<button class="btn-delete-selected disabled" onclick="recipeManager.deleteSelectedDuplicates()">
Delete Selected (<span id="duplicatesSelectedCount">0</span>)
{{ t('recipes.duplicates.deleteSelected') }} (<span id="duplicatesSelectedCount">0</span>)
</button>
<button class="btn-exit" onclick="recipeManager.exitDuplicateMode()">
<i class="fas fa-times"></i>

View File

@@ -1,6 +1,6 @@
{% extends "base.html" %}
{% block title %}Statistics - LoRA Manager{% endblock %}
{% block title %}{{ t('statistics.title') }} - {{ t('header.appTitle') }}{% endblock %}
{% block page_id %}statistics{% endblock %}
{% block preload %}
@@ -14,8 +14,8 @@
<script src="/loras_static/vendor/chart.js/chart.umd.js"></script>
{% endblock %}
{% block init_title %}Initializing Statistics{% endblock %}
{% block init_message %}Loading model data and usage statistics. This may take a moment...{% endblock %}
{% block init_title %}{{ t('initialization.statistics.title') }}{% endblock %}
{% block init_message %}{{ t('initialization.statistics.message') }}{% endblock %}
{% block init_check_url %}/api/stats/collection-overview{% endblock %}
{% block content %}
@@ -32,19 +32,19 @@
<!-- Navigation Tabs -->
<div class="dashboard-tabs">
<button class="tab-button active" data-tab="overview">
<i class="fas fa-chart-bar"></i> Overview
<i class="fas fa-chart-bar"></i> {{ t('statistics.tabs.overview') }}
</button>
<button class="tab-button" data-tab="usage">
<i class="fas fa-chart-line"></i> Usage Analysis
<i class="fas fa-chart-line"></i> {{ t('statistics.tabs.usage') }}
</button>
<button class="tab-button" data-tab="collection">
<i class="fas fa-layer-group"></i> Collection
<i class="fas fa-layer-group"></i> {{ t('statistics.tabs.collection') }}
</button>
<button class="tab-button" data-tab="storage">
<i class="fas fa-hdd"></i> Storage
<i class="fas fa-hdd"></i> {{ t('statistics.tabs.storage') }}
</button>
<button class="tab-button" data-tab="insights">
<i class="fas fa-lightbulb"></i> Insights
<i class="fas fa-lightbulb"></i> {{ t('statistics.tabs.insights') }}
</button>
</div>

183
test_i18n.py Normal file
View File

@@ -0,0 +1,183 @@
#!/usr/bin/env python3
"""
Test script to verify the updated i18n system works correctly.
This tests both JavaScript loading and Python server-side functionality.
"""
import os
import sys
import json
import asyncio
# Add the parent directory to the path so we can import the modules
sys.path.insert(0, os.path.dirname(os.path.dirname(__file__)))
def test_json_files_exist():
"""Test that all JSON locale files exist and are valid JSON."""
print("Testing JSON locale files...")
locales_dir = os.path.join(os.path.dirname(__file__), 'locales')
if not os.path.exists(locales_dir):
print("❌ Locales directory does not exist!")
return False
expected_locales = ['en', 'zh-CN', 'zh-TW', 'ja', 'ru', 'de', 'fr', 'es', 'ko']
for locale in expected_locales:
file_path = os.path.join(locales_dir, f'{locale}.json')
if not os.path.exists(file_path):
print(f"{locale}.json does not exist!")
return False
try:
with open(file_path, 'r', encoding='utf-8') as f:
data = json.load(f)
# Check that required sections exist
required_sections = ['common', 'header', 'loras', 'recipes', 'modals']
for section in required_sections:
if section not in data:
print(f"{locale}.json missing required section: {section}")
return False
print(f"{locale}.json is valid")
except json.JSONDecodeError as e:
print(f"{locale}.json has invalid JSON: {e}")
return False
except Exception as e:
print(f"❌ Error reading {locale}.json: {e}")
return False
print("✅ All JSON locale files are valid")
return True
def test_server_i18n():
"""Test the Python server-side i18n system."""
print("\nTesting Python server-side i18n...")
try:
from py.services.server_i18n import ServerI18nManager
# Create a new instance to test
i18n = ServerI18nManager()
# Test that translations loaded
available_locales = i18n.get_available_locales()
if not available_locales:
print("❌ No locales loaded in server i18n!")
return False
print(f"✅ Loaded {len(available_locales)} locales: {', '.join(available_locales)}")
# Test English translations
i18n.set_locale('en')
test_key = 'common.status.loading'
translation = i18n.get_translation(test_key)
if translation == test_key:
print(f"❌ Translation not found for key '{test_key}'")
return False
print(f"✅ English translation for '{test_key}': '{translation}'")
# Test Chinese translations
i18n.set_locale('zh-CN')
translation_cn = i18n.get_translation(test_key)
if translation_cn == test_key:
print(f"❌ Chinese translation not found for key '{test_key}'")
return False
print(f"✅ Chinese translation for '{test_key}': '{translation_cn}'")
# Test parameter interpolation
param_key = 'common.itemCount'
translation_with_params = i18n.get_translation(param_key, count=42)
if '{count}' in translation_with_params:
print(f"❌ Parameter interpolation failed for key '{param_key}'")
return False
print(f"✅ Parameter interpolation for '{param_key}': '{translation_with_params}'")
print("✅ Server-side i18n system working correctly")
return True
except Exception as e:
print(f"❌ Error testing server i18n: {e}")
import traceback
traceback.print_exc()
return False
def test_translation_completeness():
"""Test that all languages have the same translation keys."""
print("\nTesting translation completeness...")
locales_dir = os.path.join(os.path.dirname(__file__), 'locales')
# Load English as reference
with open(os.path.join(locales_dir, 'en.json'), 'r', encoding='utf-8') as f:
en_data = json.load(f)
def get_all_keys(data, prefix=''):
"""Recursively get all keys from nested dictionary."""
keys = set()
for key, value in data.items():
full_key = f"{prefix}.{key}" if prefix else key
keys.add(full_key)
if isinstance(value, dict):
keys.update(get_all_keys(value, full_key))
return keys
en_keys = get_all_keys(en_data)
print(f"English has {len(en_keys)} translation keys")
# Check other languages
locales = ['zh-CN', 'zh-TW', 'ja', 'ru', 'de', 'fr', 'es', 'ko']
for locale in locales:
with open(os.path.join(locales_dir, f'{locale}.json'), 'r', encoding='utf-8') as f:
locale_data = json.load(f)
locale_keys = get_all_keys(locale_data)
missing_keys = en_keys - locale_keys
extra_keys = locale_keys - en_keys
if missing_keys:
print(f"{locale} missing keys: {len(missing_keys)}")
# Print first few missing keys
for key in sorted(missing_keys)[:5]:
print(f" - {key}")
if len(missing_keys) > 5:
print(f" ... and {len(missing_keys) - 5} more")
if extra_keys:
print(f"⚠️ {locale} has extra keys: {len(extra_keys)}")
if not missing_keys and not extra_keys:
print(f"{locale} has complete translations ({len(locale_keys)} keys)")
return True
def main():
"""Run all tests."""
print("🚀 Testing updated i18n system...\n")
success = True
# Test JSON files
if not test_json_files_exist():
success = False
# Test server i18n
if not test_server_i18n():
success = False
# Test completeness
if not test_translation_completeness():
success = False
print(f"\n{'🎉 All tests passed!' if success else '❌ Some tests failed!'}")
return success
if __name__ == '__main__':
main()