diff --git a/tagstudio/resources/translations/en.json b/tagstudio/resources/translations/en.json index 8b9542785..69e041b84 100644 --- a/tagstudio/resources/translations/en.json +++ b/tagstudio/resources/translations/en.json @@ -157,6 +157,9 @@ "macros.running.dialog.new_entries": "Running Configured Macros on {count}/{total} New File Entries...", "macros.running.dialog.title": "Running Macros on New Entries", "media_player.autoplay": "Autoplay", + "menu.delete_selected_files_ambiguous": "Move File(s) to {trash_term}", + "menu.delete_selected_files_plural": "Move Files to {trash_term}", + "menu.delete_selected_files_singular": "Move File to {trash_term}", "menu.edit.ignore_list": "Ignore Files and Folders", "menu.edit.manage_file_extensions": "Manage File Extensions", "menu.edit.manage_tags": "Manage Tags", @@ -195,6 +198,11 @@ "sorting.direction.ascending": "Ascending", "sorting.direction.descending": "Descending", "splash.opening_library": "Opening Library \"{library_path}\"...", + "status.deleted_file_plural": "Deleting {count} files!", + "status.deleted_file_singular": "Deleting 1 file!", + "status.deleted_none": "Deleting file [{i}/{count}]: \"{path}\"...", + "status.deleted_partial_warning": "Only deleted {count} file(s)! Check if any of the files are currently missing or in use.", + "status.deleting_file": "Deleting file [{i}/{count}]: \"{path}\"...", "status.library_backup_in_progress": "Saving Library Backup...", "status.library_backup_success": "Library Backup Saved at: \"{path}\" ({time_span})", "status.library_closed": "Library Closed ({time_span})", @@ -228,6 +236,18 @@ "tag.search_for_tag": "Search for Tag", "tag.shorthand": "Shorthand", "tag.tag_name_required": "Tag Name (Required)", + "trash.context.ambiguous": "Move file(s) to {trash_term}", + "trash.context.plural": "Move files to {trash_term}", + "trash.context.singular": "Move file to {trash_term}", + "trash.dialog.disambiguation_warning.plural": "This will remove them from TagStudio AND your file system!", + "trash.dialog.disambiguation_warning.singular": "This will remove it from TagStudio AND your file system!", + "trash.dialog.move.confirmation.plural": "Are you sure you want to move these {count} files to the {trash_term}?", + "trash.dialog.move.confirmation.singular": "Are you sure you want to move this file to the {trash_term}?", + "trash.dialog.permanent_delete_warning": "WARNING! If this file can't be moved to the {trash_term}, it will be permanently deleted!", + "trash.dialog.title.plural": "Delete Files", + "trash.dialog.title.singular": "Delete File", + "trash.name.recycle_bin": "Recycle Bin", + "trash.name.trash": "Trash", "view.size.0": "Mini", "view.size.1": "Small", "view.size.2": "Medium", diff --git a/tagstudio/src/qt/helpers/file_deleter.py b/tagstudio/src/qt/helpers/file_deleter.py index 4a94e6be5..a8e50e17c 100644 --- a/tagstudio/src/qt/helpers/file_deleter.py +++ b/tagstudio/src/qt/helpers/file_deleter.py @@ -11,7 +11,7 @@ def delete_file(path: str | Path) -> bool: - """Sends a file to the system trash. + """Send a file to the system trash. Args: path (str | Path): The path of the file to delete. diff --git a/tagstudio/src/qt/ts_qt.py b/tagstudio/src/qt/ts_qt.py index 84674f54b..3d5348fa7 100644 --- a/tagstudio/src/qt/ts_qt.py +++ b/tagstudio/src/qt/ts_qt.py @@ -488,9 +488,17 @@ def start(self) -> None: edit_menu.addSeparator() - self.delete_file_action = QAction("Delete Selected File(s)", menu_bar) + self.delete_file_action = QAction(menu_bar) + trash_term: str = Translations["trash.name.trash"] + if platform.system() == "Windows": + trash_term = Translations["trash.name.recycle_bin"] + + Translations.translate_qobject( + self.delete_file_action, "menu.delete_selected_files_ambiguous", trash_term=trash_term + ) self.delete_file_action.triggered.connect(lambda f="": self.delete_files_callback(f)) self.delete_file_action.setShortcut(QtCore.Qt.Key.Key_Delete) + self.delete_file_action.setEnabled(False) edit_menu.addAction(self.delete_file_action) edit_menu.addSeparator() @@ -816,10 +824,13 @@ def close_library(self, is_shutdown: bool = False): self.main_window.setWindowTitle(self.base_title) - self.selected = [] - self.frame_content = [] + self.selected.clear() + self.frame_content.clear() [x.set_mode(None) for x in self.item_thumbs] + self.set_clipboard_menu_viability() + self.set_add_to_selected_visibility() + self.preview_panel.update_widgets() self.main_window.toggle_landing_page(enabled=True) self.main_window.pagination.setHidden(True) @@ -955,7 +966,9 @@ def delete_files_callback(self, origin_path: str | Path, origin_id: int | None = self.preview_panel.thumb.stop_file_use() if delete_file(self.lib.library_dir / f): self.main_window.statusbar.showMessage( - f'Deleting file [{i}/{len(pending)}]: "{f}"...' + Translations.translate_formatted( + "status.deleting_file", i=i, count=len(pending), path=f + ) ) self.main_window.statusbar.repaint() self.lib.remove_entries([e_id]) @@ -968,18 +981,23 @@ def delete_files_callback(self, origin_path: str | Path, origin_id: int | None = self.preview_panel.update_widgets() if len(self.selected) <= 1 and deleted_count == 0: - self.main_window.statusbar.showMessage("No files deleted.") + self.main_window.statusbar.showMessage(Translations["status.deleted_none"]) elif len(self.selected) <= 1 and deleted_count == 1: - self.main_window.statusbar.showMessage(f"Deleted {deleted_count} file!") + self.main_window.statusbar.showMessage( + Translations.translate_formatted("status.deleted_file_plural", count=deleted_count) + ) elif len(self.selected) > 1 and deleted_count == 0: - self.main_window.statusbar.showMessage("No files deleted.") + self.main_window.statusbar.showMessage(Translations["status.deleted_none"]) elif len(self.selected) > 1 and deleted_count < len(self.selected): self.main_window.statusbar.showMessage( - f"Only deleted {deleted_count} file{'' if deleted_count == 1 else 's'}! " - f"Check if any of the files are currently missing or in use." + Translations.translate_formatted( + "status.deleted_partial_warning", count=deleted_count + ) ) elif len(self.selected) > 1 and deleted_count == len(self.selected): - self.main_window.statusbar.showMessage(f"Deleted {deleted_count} files!") + self.main_window.statusbar.showMessage( + Translations.translate_formatted("status.deleted_file_plural", count=deleted_count) + ) self.main_window.statusbar.repaint() def delete_file_confirmation(self, count: int, filename: Path | None = None) -> int: @@ -989,36 +1007,50 @@ def delete_file_confirmation(self, count: int, filename: Path | None = None) -> count(int): The number of files to be deleted. filename(Path | None): The filename to show if only one file is to be deleted. """ - trash_term: str = "Trash" - if platform.system == "Windows": - trash_term = "Recycle Bin" + trash_term: str = Translations["trash.name.trash"] + if platform.system() == "Windows": + trash_term = Translations["trash.name.recycle_bin"] # NOTE: Windows + send2trash will PERMANENTLY delete files which cannot be moved to the # Recycle Bin. This is done without any warning, so this message is currently the # best way I've got to inform the user. # https://github.com/arsenetar/send2trash/issues/28 # This warning is applied to all platforms until at least macOS and Linux can be verified # to not exhibit this same behavior. + perm_warning_msg = Translations.translate_formatted( + "trash.dialog.permanent_delete_warning", + trash_term=trash_term, + ) perm_warning: str = ( f"

" - f"WARNING! If this file can't be moved to the {trash_term}, " - f"it will be permanently deleted!

" + f"{perm_warning_msg}" ) msg = QMessageBox() + msg.setStyleSheet("font-weight:normal;") msg.setTextFormat(Qt.TextFormat.RichText) - msg.setWindowTitle("Delete File" if count == 1 else "Delete Files") + msg.setWindowTitle( + Translations["trash.title.singular"] + if count == 1 + else Translations["trash.title.plural"] + ) msg.setIcon(QMessageBox.Icon.Warning) if count <= 1: + msg_text = Translations.translate_formatted( + "trash.dialog.move.confirmation.singular", trash_term=trash_term + ) msg.setText( - f"

Are you sure you want to move this file to the {trash_term}?

" - "

This will remove it from TagStudio AND your file system!

" + f"

{msg_text}

" + f"

{Translations["trash.dialog.disambiguation_warning.singular"]}

" f"{filename if filename else ''}" f"{perm_warning}
" ) elif count > 1: + msg_text = Translations.translate_formatted( + "trash.dialog.move.confirmation.plural", count=count, trash_term=trash_term + ) msg.setText( - f"

Are you sure you want to move these {count} files to the {trash_term}?

" - "

This will remove them from TagStudio AND your file system!

" + f"

{msg_text}

" + f"

{Translations["trash.dialog.disambiguation_warning.plural"]}

" f"{perm_warning}
" ) @@ -1428,9 +1460,11 @@ def set_select_actions_visibility(self): if self.selected: self.add_tag_to_selected_action.setEnabled(True) self.clear_select_action.setEnabled(True) + self.delete_file_action.setEnabled(True) else: self.add_tag_to_selected_action.setEnabled(False) self.clear_select_action.setEnabled(False) + self.delete_file_action.setEnabled(False) def update_completions_list(self, text: str) -> None: matches = re.search( diff --git a/tagstudio/src/qt/widgets/item_thumb.py b/tagstudio/src/qt/widgets/item_thumb.py index 694e66bc8..4c0c245f4 100644 --- a/tagstudio/src/qt/widgets/item_thumb.py +++ b/tagstudio/src/qt/widgets/item_thumb.py @@ -223,10 +223,13 @@ def __init__( open_explorer_action = QAction(PlatformStrings.open_file_str, self) open_explorer_action.triggered.connect(self.opener.open_explorer) - trash_term: str = "Trash" + trash_term: str = Translations["trash.name.trash"] if platform.system() == "Windows": - trash_term = "Recycle Bin" - self.delete_action: QAction = QAction(f"Send file to {trash_term}", self) + trash_term = Translations["trash.name.recycle_bin"] + self.delete_action = QAction(self) + Translations.translate_qobject( + self.delete_action, "trash.context.ambiguous", trash_term=trash_term + ) self.thumb_button.addAction(open_file_action) self.thumb_button.addAction(open_explorer_action) diff --git a/tagstudio/src/qt/widgets/preview/preview_thumb.py b/tagstudio/src/qt/widgets/preview/preview_thumb.py index d5e397265..99a5ba9f2 100644 --- a/tagstudio/src/qt/widgets/preview/preview_thumb.py +++ b/tagstudio/src/qt/widgets/preview/preview_thumb.py @@ -58,10 +58,13 @@ def __init__(self, library: Library, driver: "QtDriver"): self.open_file_action = QAction(self) Translations.translate_qobject(self.open_file_action, "file.open_file") self.open_explorer_action = QAction(PlatformStrings.open_file_str, self) - self.trash_term: str = "Trash" + self.trash_term: str = Translations["trash.name.trash"] if platform.system() == "Windows": - self.trash_term = "Recycle Bin" - self.delete_action = QAction(f"Send file to {self.trash_term}", self) + self.trash_term = Translations["trash.name.recycle_bin"] + self.delete_action = QAction(self) + Translations.translate_qobject( + self.delete_action, "trash.context.ambiguous", trash_term=self.trash_term + ) self.preview_img = QPushButtonWrapper() self.preview_img.setMinimumSize(*self.img_button_size)