chore(i18n): add undo-delete and delete-confirmation strings

This commit is contained in:
Will Miao
2026-08-11 14:08:41 +08:00
parent 1da2433bb2
commit 0bf87f9092
11 changed files with 226 additions and 10 deletions
+13 -1
View File
@@ -443,6 +443,7 @@
"label": "Bereits heruntergeladene Modellversionen überspringen", "label": "Bereits heruntergeladene Modellversionen überspringen",
"help": "Wenn aktiviert, überspringt LoRA Manager den Download einer Modellversion, wenn der Download-Verlaufsdienst diese spezifische Version als bereits heruntergeladen erfasst hat. Gilt für alle Download-Abläufe." "help": "Wenn aktiviert, überspringt LoRA Manager den Download einer Modellversion, wenn der Download-Verlaufsdienst diese spezifische Version als bereits heruntergeladen erfasst hat. Gilt für alle Download-Abläufe."
}, },
"deleteUndoEnabled": "[TODO: Translate] Keep deleted items recoverable for 30 seconds (undo)",
"layoutSettings": { "layoutSettings": {
"groupByModel": "Nach Modell gruppieren", "groupByModel": "Nach Modell gruppieren",
"groupByModelHelp": "Wenn aktiviert, wird nur die neueste Version jedes Civitai-Modells als einzelne Karte angezeigt. Ältere Versionen werden ausgeblendet.", "groupByModelHelp": "Wenn aktiviert, wird nur die neueste Version jedes Civitai-Modells als einzelne Karte angezeigt. Ältere Versionen werden ausgeblendet.",
@@ -1277,8 +1278,11 @@
} }
}, },
"deleteModel": { "deleteModel": {
"freesSpace": "[TODO: Translate] Frees {size}",
"title": "Modell löschen", "title": "Modell löschen",
"message": "Sind Sie sicher, dass Sie dieses Modell und alle zugehörigen Dateien löschen möchten?" "message": "Sind Sie sicher, dass Sie dieses Modell und alle zugehörigen Dateien löschen möchten?",
"permanentWarning": "[TODO: Translate] This will permanently delete the file from disk.",
"recoverableWarning": "[TODO: Translate] This will permanently delete the file after 30 seconds unless you undo."
}, },
"excludeModel": { "excludeModel": {
"title": "Modell ausschließen", "title": "Modell ausschließen",
@@ -2113,6 +2117,14 @@
"updateFailed": "Fehler beim Aktualisieren der Trigger Words", "updateFailed": "Fehler beim Aktualisieren der Trigger Words",
"copyFailed": "Kopieren fehlgeschlagen" "copyFailed": "Kopieren fehlgeschlagen"
}, },
"undo": {
"action": "[TODO: Translate] Undo",
"deleted": "[TODO: Translate] Deleted {name}",
"deletedBulk": "[TODO: Translate] Deleted {count} item(s)",
"expired": "[TODO: Translate] Undo window expired. The item was permanently deleted.",
"failed": "[TODO: Translate] Undo failed: {error}",
"restored": "[TODO: Translate] Item restored"
},
"virtual": { "virtual": {
"loadFailed": "Fehler beim Laden der Elemente", "loadFailed": "Fehler beim Laden der Elemente",
"loadMoreFailed": "Fehler beim Laden weiterer Elemente", "loadMoreFailed": "Fehler beim Laden weiterer Elemente",
+13 -1
View File
@@ -443,6 +443,7 @@
"label": "Skip previously downloaded model versions", "label": "Skip previously downloaded model versions",
"help": "When enabled, versions downloaded before will be skipped." "help": "When enabled, versions downloaded before will be skipped."
}, },
"deleteUndoEnabled": "Keep deleted items recoverable for 30 seconds (undo)",
"layoutSettings": { "layoutSettings": {
"groupByModel": "Group by Model", "groupByModel": "Group by Model",
"groupByModelHelp": "When enabled, only the latest version of each Civitai model is shown as a single card. Older versions are hidden.", "groupByModelHelp": "When enabled, only the latest version of each Civitai model is shown as a single card. Older versions are hidden.",
@@ -1277,8 +1278,11 @@
} }
}, },
"deleteModel": { "deleteModel": {
"freesSpace": "Frees {size}",
"title": "Delete Model", "title": "Delete Model",
"message": "Are you sure you want to delete this model and all associated files?" "message": "Are you sure you want to delete this model and all associated files?",
"permanentWarning": "This will permanently delete the file from disk.",
"recoverableWarning": "This will permanently delete the file after 30 seconds unless you undo."
}, },
"excludeModel": { "excludeModel": {
"title": "Exclude Model", "title": "Exclude Model",
@@ -2113,6 +2117,14 @@
"updateFailed": "Failed to update trigger words", "updateFailed": "Failed to update trigger words",
"copyFailed": "Copy failed" "copyFailed": "Copy failed"
}, },
"undo": {
"action": "Undo",
"deleted": "Deleted {name}",
"deletedBulk": "Deleted {count} item(s)",
"expired": "Undo window expired. The item was permanently deleted.",
"failed": "Undo failed: {error}",
"restored": "Item restored"
},
"virtual": { "virtual": {
"loadFailed": "Failed to load items", "loadFailed": "Failed to load items",
"loadMoreFailed": "Failed to load more items", "loadMoreFailed": "Failed to load more items",
+13 -1
View File
@@ -443,6 +443,7 @@
"label": "Omitir versiones de modelos previamente descargadas", "label": "Omitir versiones de modelos previamente descargadas",
"help": "Cuando está habilitado, LoRA Manager omitirá la descarga de una versión de modelo si el servicio de historial de descargas registra esa versión exacta como ya descargada. Aplica a todos los flujos de descarga." "help": "Cuando está habilitado, LoRA Manager omitirá la descarga de una versión de modelo si el servicio de historial de descargas registra esa versión exacta como ya descargada. Aplica a todos los flujos de descarga."
}, },
"deleteUndoEnabled": "[TODO: Translate] Keep deleted items recoverable for 30 seconds (undo)",
"layoutSettings": { "layoutSettings": {
"groupByModel": "Agrupar por modelo", "groupByModel": "Agrupar por modelo",
"groupByModelHelp": "Cuando está activado, solo se muestra la versión más reciente de cada modelo de Civitai como una tarjeta única. Las versiones anteriores están ocultas.", "groupByModelHelp": "Cuando está activado, solo se muestra la versión más reciente de cada modelo de Civitai como una tarjeta única. Las versiones anteriores están ocultas.",
@@ -1277,8 +1278,11 @@
} }
}, },
"deleteModel": { "deleteModel": {
"freesSpace": "[TODO: Translate] Frees {size}",
"title": "Eliminar modelo", "title": "Eliminar modelo",
"message": "¿Estás seguro de que quieres eliminar este modelo y todos los archivos asociados?" "message": "¿Estás seguro de que quieres eliminar este modelo y todos los archivos asociados?",
"permanentWarning": "[TODO: Translate] This will permanently delete the file from disk.",
"recoverableWarning": "[TODO: Translate] This will permanently delete the file after 30 seconds unless you undo."
}, },
"excludeModel": { "excludeModel": {
"title": "Excluir modelo", "title": "Excluir modelo",
@@ -2113,6 +2117,14 @@
"updateFailed": "Error al actualizar palabras clave", "updateFailed": "Error al actualizar palabras clave",
"copyFailed": "Error al copiar" "copyFailed": "Error al copiar"
}, },
"undo": {
"action": "[TODO: Translate] Undo",
"deleted": "[TODO: Translate] Deleted {name}",
"deletedBulk": "[TODO: Translate] Deleted {count} item(s)",
"expired": "[TODO: Translate] Undo window expired. The item was permanently deleted.",
"failed": "[TODO: Translate] Undo failed: {error}",
"restored": "[TODO: Translate] Item restored"
},
"virtual": { "virtual": {
"loadFailed": "Error al cargar elementos", "loadFailed": "Error al cargar elementos",
"loadMoreFailed": "Error al cargar más elementos", "loadMoreFailed": "Error al cargar más elementos",
+13 -1
View File
@@ -443,6 +443,7 @@
"label": "Ignorer les versions de modèles précédemment téléchargées", "label": "Ignorer les versions de modèles précédemment téléchargées",
"help": "Lorsque activé, LoRA Manager ignorera le téléchargement d'une version de modèle si le service d'historique des téléchargements enregistre cette version exacte comme déjà téléchargée. S'applique à tous les flux de téléchargement." "help": "Lorsque activé, LoRA Manager ignorera le téléchargement d'une version de modèle si le service d'historique des téléchargements enregistre cette version exacte comme déjà téléchargée. S'applique à tous les flux de téléchargement."
}, },
"deleteUndoEnabled": "[TODO: Translate] Keep deleted items recoverable for 30 seconds (undo)",
"layoutSettings": { "layoutSettings": {
"groupByModel": "Grouper par modèle", "groupByModel": "Grouper par modèle",
"groupByModelHelp": "Lorsque activé, seule la version la plus récente de chaque modèle Civitai s'affiche sous forme de carte unique. Les versions plus anciennes sont masquées.", "groupByModelHelp": "Lorsque activé, seule la version la plus récente de chaque modèle Civitai s'affiche sous forme de carte unique. Les versions plus anciennes sont masquées.",
@@ -1277,8 +1278,11 @@
} }
}, },
"deleteModel": { "deleteModel": {
"freesSpace": "[TODO: Translate] Frees {size}",
"title": "Supprimer le modèle", "title": "Supprimer le modèle",
"message": "Êtes-vous sûr de vouloir supprimer ce modèle et tous les fichiers associés ?" "message": "Êtes-vous sûr de vouloir supprimer ce modèle et tous les fichiers associés ?",
"permanentWarning": "[TODO: Translate] This will permanently delete the file from disk.",
"recoverableWarning": "[TODO: Translate] This will permanently delete the file after 30 seconds unless you undo."
}, },
"excludeModel": { "excludeModel": {
"title": "Exclure le modèle", "title": "Exclure le modèle",
@@ -2113,6 +2117,14 @@
"updateFailed": "Échec de la mise à jour des mots-clés", "updateFailed": "Échec de la mise à jour des mots-clés",
"copyFailed": "Échec de la copie" "copyFailed": "Échec de la copie"
}, },
"undo": {
"action": "[TODO: Translate] Undo",
"deleted": "[TODO: Translate] Deleted {name}",
"deletedBulk": "[TODO: Translate] Deleted {count} item(s)",
"expired": "[TODO: Translate] Undo window expired. The item was permanently deleted.",
"failed": "[TODO: Translate] Undo failed: {error}",
"restored": "[TODO: Translate] Item restored"
},
"virtual": { "virtual": {
"loadFailed": "Échec du chargement des éléments", "loadFailed": "Échec du chargement des éléments",
"loadMoreFailed": "Échec du chargement de plus d'éléments", "loadMoreFailed": "Échec du chargement de plus d'éléments",
+13 -1
View File
@@ -443,6 +443,7 @@
"label": "דלג על גרסאות מודלים שהורדו בעבר", "label": "דלג על גרסאות מודלים שהורדו בעבר",
"help": "כאשר מופעל, LoRA Manager ידלג על הורדת גרסת מודל אם שירות היסטוריית ההורדות רושם את הגרסה המדויקת הזו ככבר שהורדה. חל על כל תהליכי ההורדה." "help": "כאשר מופעל, LoRA Manager ידלג על הורדת גרסת מודל אם שירות היסטוריית ההורדות רושם את הגרסה המדויקת הזו ככבר שהורדה. חל על כל תהליכי ההורדה."
}, },
"deleteUndoEnabled": "[TODO: Translate] Keep deleted items recoverable for 30 seconds (undo)",
"layoutSettings": { "layoutSettings": {
"groupByModel": "קיבוץ לפי דגם", "groupByModel": "קיבוץ לפי דגם",
"groupByModelHelp": "כאשר מופעל, רק הגרסה העדכנית ביותר של כל דגם Civitai מוצגת ככרטיס בודד. גרסאות ישנות יותר מוסתרות.", "groupByModelHelp": "כאשר מופעל, רק הגרסה העדכנית ביותר של כל דגם Civitai מוצגת ככרטיס בודד. גרסאות ישנות יותר מוסתרות.",
@@ -1277,8 +1278,11 @@
} }
}, },
"deleteModel": { "deleteModel": {
"freesSpace": "[TODO: Translate] Frees {size}",
"title": "מחק מודל", "title": "מחק מודל",
"message": "האם אתה בטוח שברצונך למחוק מודל זה וכל הקבצים הנלווים?" "message": "האם אתה בטוח שברצונך למחוק מודל זה וכל הקבצים הנלווים?",
"permanentWarning": "[TODO: Translate] This will permanently delete the file from disk.",
"recoverableWarning": "[TODO: Translate] This will permanently delete the file after 30 seconds unless you undo."
}, },
"excludeModel": { "excludeModel": {
"title": "החרג מודל", "title": "החרג מודל",
@@ -2113,6 +2117,14 @@
"updateFailed": "עדכון מילות הטריגר נכשל", "updateFailed": "עדכון מילות הטריגר נכשל",
"copyFailed": "ההעתקה נכשלה" "copyFailed": "ההעתקה נכשלה"
}, },
"undo": {
"action": "[TODO: Translate] Undo",
"deleted": "[TODO: Translate] Deleted {name}",
"deletedBulk": "[TODO: Translate] Deleted {count} item(s)",
"expired": "[TODO: Translate] Undo window expired. The item was permanently deleted.",
"failed": "[TODO: Translate] Undo failed: {error}",
"restored": "[TODO: Translate] Item restored"
},
"virtual": { "virtual": {
"loadFailed": "טעינת הפריטים נכשלה", "loadFailed": "טעינת הפריטים נכשלה",
"loadMoreFailed": "טעינת פריטים נוספים נכשלה", "loadMoreFailed": "טעינת פריטים נוספים נכשלה",
+13 -1
View File
@@ -443,6 +443,7 @@
"label": "以前にダウンロードしたモデルバージョンをスキップ", "label": "以前にダウンロードしたモデルバージョンをスキップ",
"help": "有効にすると、ダウンロード履歴サービスがそのバージョンが既にダウンロード済みと記録している場合、LoRA Managerはそのモデルバージョンのダウンロードをスキップします。すべてのダウンロードフローに適用されます。" "help": "有効にすると、ダウンロード履歴サービスがそのバージョンが既にダウンロード済みと記録している場合、LoRA Managerはそのモデルバージョンのダウンロードをスキップします。すべてのダウンロードフローに適用されます。"
}, },
"deleteUndoEnabled": "[TODO: Translate] Keep deleted items recoverable for 30 seconds (undo)",
"layoutSettings": { "layoutSettings": {
"groupByModel": "モデルでグループ化", "groupByModel": "モデルでグループ化",
"groupByModelHelp": "有効にすると、各Civitaiモデルの最新バージョンのみが1枚のカードとして表示され、古いバージョンは非表示になります。", "groupByModelHelp": "有効にすると、各Civitaiモデルの最新バージョンのみが1枚のカードとして表示され、古いバージョンは非表示になります。",
@@ -1277,8 +1278,11 @@
} }
}, },
"deleteModel": { "deleteModel": {
"freesSpace": "[TODO: Translate] Frees {size}",
"title": "モデルを削除", "title": "モデルを削除",
"message": "このモデルと関連するすべてのファイルを削除してもよろしいですか?" "message": "このモデルと関連するすべてのファイルを削除してもよろしいですか?",
"permanentWarning": "[TODO: Translate] This will permanently delete the file from disk.",
"recoverableWarning": "[TODO: Translate] This will permanently delete the file after 30 seconds unless you undo."
}, },
"excludeModel": { "excludeModel": {
"title": "モデルを除外", "title": "モデルを除外",
@@ -2113,6 +2117,14 @@
"updateFailed": "トリガーワードの更新に失敗しました", "updateFailed": "トリガーワードの更新に失敗しました",
"copyFailed": "コピーに失敗しました" "copyFailed": "コピーに失敗しました"
}, },
"undo": {
"action": "[TODO: Translate] Undo",
"deleted": "[TODO: Translate] Deleted {name}",
"deletedBulk": "[TODO: Translate] Deleted {count} item(s)",
"expired": "[TODO: Translate] Undo window expired. The item was permanently deleted.",
"failed": "[TODO: Translate] Undo failed: {error}",
"restored": "[TODO: Translate] Item restored"
},
"virtual": { "virtual": {
"loadFailed": "アイテムの読み込みに失敗しました", "loadFailed": "アイテムの読み込みに失敗しました",
"loadMoreFailed": "追加アイテムの読み込みに失敗しました", "loadMoreFailed": "追加アイテムの読み込みに失敗しました",
+13 -1
View File
@@ -443,6 +443,7 @@
"label": "이전에 다운로드한 모델 버전 건너뛰기", "label": "이전에 다운로드한 모델 버전 건너뛰기",
"help": "활성화하면 다운로드 기록 서비스가 해당 버전이 이미 다운로드되었음을 기록한 경우 LoRA Manager는 해당 모델 버전 다운로드를 건너뜁니다. 모든 다운로드 플로우에 적용됩니다." "help": "활성화하면 다운로드 기록 서비스가 해당 버전이 이미 다운로드되었음을 기록한 경우 LoRA Manager는 해당 모델 버전 다운로드를 건너뜁니다. 모든 다운로드 플로우에 적용됩니다."
}, },
"deleteUndoEnabled": "[TODO: Translate] Keep deleted items recoverable for 30 seconds (undo)",
"layoutSettings": { "layoutSettings": {
"groupByModel": "모델별 그룹화", "groupByModel": "모델별 그룹화",
"groupByModelHelp": "활성화하면 각 Civitai 모델의 최신 버전만 단일 카드로 표시되며, 이전 버전은 숨겨집니다.", "groupByModelHelp": "활성화하면 각 Civitai 모델의 최신 버전만 단일 카드로 표시되며, 이전 버전은 숨겨집니다.",
@@ -1277,8 +1278,11 @@
} }
}, },
"deleteModel": { "deleteModel": {
"freesSpace": "[TODO: Translate] Frees {size}",
"title": "모델 삭제", "title": "모델 삭제",
"message": "이 모델과 모든 관련 파일을 삭제하시겠습니까?" "message": "이 모델과 모든 관련 파일을 삭제하시겠습니까?",
"permanentWarning": "[TODO: Translate] This will permanently delete the file from disk.",
"recoverableWarning": "[TODO: Translate] This will permanently delete the file after 30 seconds unless you undo."
}, },
"excludeModel": { "excludeModel": {
"title": "모델 제외", "title": "모델 제외",
@@ -2113,6 +2117,14 @@
"updateFailed": "트리거 단어 업데이트에 실패했습니다", "updateFailed": "트리거 단어 업데이트에 실패했습니다",
"copyFailed": "복사 실패" "copyFailed": "복사 실패"
}, },
"undo": {
"action": "[TODO: Translate] Undo",
"deleted": "[TODO: Translate] Deleted {name}",
"deletedBulk": "[TODO: Translate] Deleted {count} item(s)",
"expired": "[TODO: Translate] Undo window expired. The item was permanently deleted.",
"failed": "[TODO: Translate] Undo failed: {error}",
"restored": "[TODO: Translate] Item restored"
},
"virtual": { "virtual": {
"loadFailed": "항목 로딩 실패", "loadFailed": "항목 로딩 실패",
"loadMoreFailed": "더 많은 항목 로딩 실패", "loadMoreFailed": "더 많은 항목 로딩 실패",
+13 -1
View File
@@ -443,6 +443,7 @@
"label": "Пропускать ранее загруженные версии моделей", "label": "Пропускать ранее загруженные версии моделей",
"help": "Если включено, LoRA Manager будет пропускать загрузку версии модели, если сервис истории загрузок записал, что эта конкретная версия уже загружена. Применяется ко всем потокам загрузки." "help": "Если включено, LoRA Manager будет пропускать загрузку версии модели, если сервис истории загрузок записал, что эта конкретная версия уже загружена. Применяется ко всем потокам загрузки."
}, },
"deleteUndoEnabled": "[TODO: Translate] Keep deleted items recoverable for 30 seconds (undo)",
"layoutSettings": { "layoutSettings": {
"groupByModel": "Группировать по модели", "groupByModel": "Группировать по модели",
"groupByModelHelp": "При включении отображается только последняя версия каждой модели Civitai в виде одной карточки. Старые версии скрыты.", "groupByModelHelp": "При включении отображается только последняя версия каждой модели Civitai в виде одной карточки. Старые версии скрыты.",
@@ -1277,8 +1278,11 @@
} }
}, },
"deleteModel": { "deleteModel": {
"freesSpace": "[TODO: Translate] Frees {size}",
"title": "Удалить модель", "title": "Удалить модель",
"message": "Вы уверены, что хотите удалить эту модель и все связанные файлы?" "message": "Вы уверены, что хотите удалить эту модель и все связанные файлы?",
"permanentWarning": "[TODO: Translate] This will permanently delete the file from disk.",
"recoverableWarning": "[TODO: Translate] This will permanently delete the file after 30 seconds unless you undo."
}, },
"excludeModel": { "excludeModel": {
"title": "Исключить модель", "title": "Исключить модель",
@@ -2113,6 +2117,14 @@
"updateFailed": "Не удалось обновить триггерные слова", "updateFailed": "Не удалось обновить триггерные слова",
"copyFailed": "Копирование не удалось" "copyFailed": "Копирование не удалось"
}, },
"undo": {
"action": "[TODO: Translate] Undo",
"deleted": "[TODO: Translate] Deleted {name}",
"deletedBulk": "[TODO: Translate] Deleted {count} item(s)",
"expired": "[TODO: Translate] Undo window expired. The item was permanently deleted.",
"failed": "[TODO: Translate] Undo failed: {error}",
"restored": "[TODO: Translate] Item restored"
},
"virtual": { "virtual": {
"loadFailed": "Не удалось загрузить элементы", "loadFailed": "Не удалось загрузить элементы",
"loadMoreFailed": "Не удалось загрузить больше элементов", "loadMoreFailed": "Не удалось загрузить больше элементов",
+13 -1
View File
@@ -443,6 +443,7 @@
"label": "跳过已下载的模型版本", "label": "跳过已下载的模型版本",
"help": "启用后,如果下载历史服务记录显示该版本已下载,LoRA Manager 将跳过下载该模型版本。适用于所有下载流程。" "help": "启用后,如果下载历史服务记录显示该版本已下载,LoRA Manager 将跳过下载该模型版本。适用于所有下载流程。"
}, },
"deleteUndoEnabled": "[TODO: Translate] Keep deleted items recoverable for 30 seconds (undo)",
"layoutSettings": { "layoutSettings": {
"groupByModel": "按模型分组", "groupByModel": "按模型分组",
"groupByModelHelp": "开启后,每个 Civitai 模型仅显示最新版本的单张卡片,旧版本将被隐藏。", "groupByModelHelp": "开启后,每个 Civitai 模型仅显示最新版本的单张卡片,旧版本将被隐藏。",
@@ -1277,8 +1278,11 @@
} }
}, },
"deleteModel": { "deleteModel": {
"freesSpace": "[TODO: Translate] Frees {size}",
"title": "删除模型", "title": "删除模型",
"message": "你确定要删除此模型及所有相关文件吗?" "message": "你确定要删除此模型及所有相关文件吗?",
"permanentWarning": "[TODO: Translate] This will permanently delete the file from disk.",
"recoverableWarning": "[TODO: Translate] This will permanently delete the file after 30 seconds unless you undo."
}, },
"excludeModel": { "excludeModel": {
"title": "排除模型", "title": "排除模型",
@@ -2113,6 +2117,14 @@
"updateFailed": "触发词更新失败", "updateFailed": "触发词更新失败",
"copyFailed": "复制失败" "copyFailed": "复制失败"
}, },
"undo": {
"action": "[TODO: Translate] Undo",
"deleted": "[TODO: Translate] Deleted {name}",
"deletedBulk": "[TODO: Translate] Deleted {count} item(s)",
"expired": "[TODO: Translate] Undo window expired. The item was permanently deleted.",
"failed": "[TODO: Translate] Undo failed: {error}",
"restored": "[TODO: Translate] Item restored"
},
"virtual": { "virtual": {
"loadFailed": "加载项目失败", "loadFailed": "加载项目失败",
"loadMoreFailed": "加载更多项目失败", "loadMoreFailed": "加载更多项目失败",
+13 -1
View File
@@ -443,6 +443,7 @@
"label": "跳過已下載的模型版本", "label": "跳過已下載的模型版本",
"help": "啟用後,如果下載歷史服務記錄顯示該版本已下載,LoRA Manager 將跳過下載該模型版本。適用於所有下載流程。" "help": "啟用後,如果下載歷史服務記錄顯示該版本已下載,LoRA Manager 將跳過下載該模型版本。適用於所有下載流程。"
}, },
"deleteUndoEnabled": "[TODO: Translate] Keep deleted items recoverable for 30 seconds (undo)",
"layoutSettings": { "layoutSettings": {
"groupByModel": "按模型分組", "groupByModel": "按模型分組",
"groupByModelHelp": "啟用後,每個 Civitai 模型僅顯示最新版本的單張卡片,舊版本將被隱藏。", "groupByModelHelp": "啟用後,每個 Civitai 模型僅顯示最新版本的單張卡片,舊版本將被隱藏。",
@@ -1277,8 +1278,11 @@
} }
}, },
"deleteModel": { "deleteModel": {
"freesSpace": "[TODO: Translate] Frees {size}",
"title": "刪除模型", "title": "刪除模型",
"message": "您確定要刪除此模型及所有相關檔案嗎?" "message": "您確定要刪除此模型及所有相關檔案嗎?",
"permanentWarning": "[TODO: Translate] This will permanently delete the file from disk.",
"recoverableWarning": "[TODO: Translate] This will permanently delete the file after 30 seconds unless you undo."
}, },
"excludeModel": { "excludeModel": {
"title": "排除模型", "title": "排除模型",
@@ -2113,6 +2117,14 @@
"updateFailed": "更新觸發詞失敗", "updateFailed": "更新觸發詞失敗",
"copyFailed": "複製失敗" "copyFailed": "複製失敗"
}, },
"undo": {
"action": "[TODO: Translate] Undo",
"deleted": "[TODO: Translate] Deleted {name}",
"deletedBulk": "[TODO: Translate] Deleted {count} item(s)",
"expired": "[TODO: Translate] Undo window expired. The item was permanently deleted.",
"failed": "[TODO: Translate] Undo failed: {error}",
"restored": "[TODO: Translate] Item restored"
},
"virtual": { "virtual": {
"loadFailed": "載入項目失敗", "loadFailed": "載入項目失敗",
"loadMoreFailed": "載入更多項目失敗", "loadMoreFailed": "載入更多項目失敗",
+96
View File
@@ -0,0 +1,96 @@
import { describe, it, afterEach, expect, vi } from 'vitest';
import { readFileSync } from 'node:fs';
import { fileURLToPath } from 'node:url';
import { dirname, resolve } from 'node:path';
import { translate } from '../../../static/js/utils/i18nHelpers.js';
const repoRoot = resolve(dirname(fileURLToPath(import.meta.url)), '../../..');
/**
* Real en.json translations backed by a minimal `window.i18n` stub that mirrors
* the nested lookup + {param} interpolation of static/js/i18n/index.js, so the
* assertions exercise actual key resolution rather than key presence.
*/
const loadEnTranslations = () =>
JSON.parse(readFileSync(resolve(repoRoot, 'locales/en.json'), 'utf8'));
const installWindowI18n = () => {
const translations = loadEnTranslations();
const interpolate = (str, params) =>
str.replace(/\{\{?(\w+)\}?\}/g, (match, key) =>
params[key] !== undefined ? params[key] : match,
);
window.i18n = {
t: (key, params = {}) => {
const keys = key.split('.');
let value = translations;
for (const k of keys) {
if (value && typeof value === 'object' && k in value) {
value = value[k];
} else {
console.warn(`Translation key not found: ${key}`);
return key;
}
}
if (typeof value !== 'string') {
console.warn(`Translation key is not a string: ${key}`);
return key;
}
return interpolate(value, params);
},
getCurrentLocale: () => 'en',
};
};
afterEach(() => {
delete window.i18n;
});
describe('translate() with real en.json locale', () => {
it('resolves undo toast keys with interpolation', () => {
installWindowI18n();
expect(translate('toast.undo.deleted', { name: 'x' })).toBe('Deleted x');
expect(translate('toast.undo.deletedBulk', { count: 3 })).toBe('Deleted 3 item(s)');
expect(translate('toast.undo.action')).toBe('Undo');
expect(translate('toast.undo.restored')).toBe('Item restored');
expect(translate('toast.undo.expired')).toBe(
'Undo window expired. The item was permanently deleted.',
);
expect(translate('toast.undo.failed', { error: 'boom' })).toBe('Undo failed: boom');
});
it('resolves delete-model modal keys with interpolation', () => {
installWindowI18n();
expect(translate('modals.deleteModel.permanentWarning')).toBe(
'This will permanently delete the file from disk.',
);
expect(translate('modals.deleteModel.recoverableWarning')).toBe(
'This will permanently delete the file after 30 seconds unless you undo.',
);
expect(translate('modals.deleteModel.freesSpace', { size: '1.2 MB' })).toBe(
'Frees 1.2 MB',
);
});
it('resolves the delete-undo settings label', () => {
installWindowI18n();
expect(translate('settings.deleteUndoEnabled')).toBe(
'Keep deleted items recoverable for 30 seconds (undo)',
);
});
it('returns the raw key when no translation exists (fallback contract)', () => {
installWindowI18n();
const warnSpy = vi.spyOn(console, 'warn').mockImplementation(() => {});
expect(translate('toast.undo.nonExistentKey')).toBe('toast.undo.nonExistentKey');
warnSpy.mockRestore();
});
});