From 82f7c24f34d947f52f2ada35e6402a777ece7827 Mon Sep 17 00:00:00 2001 From: mattsu Date: Thu, 25 Dec 2025 20:46:59 +0900 Subject: [PATCH 1/2] feat(rm): add localized prompt messages for interactive mode Add translations for rm command prompts in English and French, and update Linux-specific code to use localized strings instead of hardcoded messages, improving internationalization support. --- src/uu/rm/locales/en-US.ftl | 19 +++++++ src/uu/rm/locales/fr-FR.ftl | 19 +++++++ src/uu/rm/src/platform/linux.rs | 57 +++++++++++++++---- src/uu/rm/src/rm.rs | 98 ++++++++++++++++++++++----------- 4 files changed, 150 insertions(+), 43 deletions(-) diff --git a/src/uu/rm/locales/en-US.ftl b/src/uu/rm/locales/en-US.ftl index a84f746f231..dea5f26c87d 100644 --- a/src/uu/rm/locales/en-US.ftl +++ b/src/uu/rm/locales/en-US.ftl @@ -33,6 +33,25 @@ rm-help-progress = display a progress bar. Note: this feature is not supported b # Progress messages rm-progress-removing = Removing +# Prompt messages +rm-prompt-remove-arguments = remove { $count -> + [one] { $count } argument? + *[other] { $count } arguments? +} +rm-prompt-remove-arguments-recursive = remove { $count -> + [one] { $count } argument recursively? + *[other] { $count } arguments recursively? +} +rm-prompt-remove-symbolic-link = remove symbolic link { $file }? +rm-prompt-remove-regular-empty-file = remove regular empty file { $file }? +rm-prompt-remove-file = remove file { $file }? +rm-prompt-remove-write-protected-regular-empty-file = remove write-protected regular empty file { $file }? +rm-prompt-remove-write-protected-regular-file = remove write-protected regular file { $file }? +rm-prompt-attempt-remove-inaccessible-directory = attempt removal of inaccessible directory { $path }? +rm-prompt-remove-write-protected-directory = remove write-protected directory { $path }? +rm-prompt-remove-directory = remove directory { $path }? +rm-prompt-descend-into-directory = descend into directory { $path }? + # Error messages rm-error-missing-operand = missing operand Try '{$util_name} --help' for more information. diff --git a/src/uu/rm/locales/fr-FR.ftl b/src/uu/rm/locales/fr-FR.ftl index a3da4ba0b2b..49c62b10c1e 100644 --- a/src/uu/rm/locales/fr-FR.ftl +++ b/src/uu/rm/locales/fr-FR.ftl @@ -33,6 +33,25 @@ rm-help-progress = afficher une barre de progression. Note : cette fonctionnalit # Messages de progression rm-progress-removing = Suppression +# Messages de confirmation +rm-prompt-remove-arguments = supprimer { $count -> + [one] { $count } argument ? + *[other] { $count } arguments ? +} +rm-prompt-remove-arguments-recursive = supprimer { $count -> + [one] { $count } argument récursivement ? + *[other] { $count } arguments récursivement ? +} +rm-prompt-remove-symbolic-link = supprimer le lien symbolique { $file } ? +rm-prompt-remove-regular-empty-file = supprimer le fichier ordinaire vide { $file } ? +rm-prompt-remove-file = supprimer le fichier { $file } ? +rm-prompt-remove-write-protected-regular-empty-file = supprimer le fichier ordinaire vide protégé en écriture { $file } ? +rm-prompt-remove-write-protected-regular-file = supprimer le fichier ordinaire protégé en écriture { $file } ? +rm-prompt-attempt-remove-inaccessible-directory = tenter de supprimer le répertoire inaccessible { $path } ? +rm-prompt-remove-write-protected-directory = supprimer le répertoire protégé en écriture { $path } ? +rm-prompt-remove-directory = supprimer le répertoire { $path } ? +rm-prompt-descend-into-directory = descendre dans le répertoire { $path } ? + # Messages d'erreur rm-error-missing-operand = opérande manquant Essayez '{$util_name} --help' pour plus d'informations. diff --git a/src/uu/rm/src/platform/linux.rs b/src/uu/rm/src/platform/linux.rs index 3e29bf85e7f..596ffe12161 100644 --- a/src/uu/rm/src/platform/linux.rs +++ b/src/uu/rm/src/platform/linux.rs @@ -52,13 +52,22 @@ fn prompt_file_with_stat(path: &Path, stat: &libc::stat, options: &Options) -> b // otherwise fall through to protected wording. if options.interactive == InteractiveMode::Always { if is_symlink { - return prompt_yes!("remove symbolic link {}?", path.quote()); + return prompt_yes!( + "{}", + translate!("rm-prompt-remove-symbolic-link", "file" => path.quote()) + ); } if writable { return if len == 0 { - prompt_yes!("remove regular empty file {}?", path.quote()) + prompt_yes!( + "{}", + translate!("rm-prompt-remove-regular-empty-file", "file" => path.quote()) + ) } else { - prompt_yes!("remove file {}?", path.quote()) + prompt_yes!( + "{}", + translate!("rm-prompt-remove-file", "file" => path.quote()) + ) }; } // Not writable: use protected wording below @@ -69,10 +78,19 @@ fn prompt_file_with_stat(path: &Path, stat: &libc::stat, options: &Options) -> b (false, _, _) if options.interactive == InteractiveMode::PromptProtected => true, (_, true, _) => true, (_, false, true) => prompt_yes!( - "remove write-protected regular empty file {}?", - path.quote() + "{}", + translate!( + "rm-prompt-remove-write-protected-regular-empty-file", + "file" => path.quote() + ) + ), + _ => prompt_yes!( + "{}", + translate!( + "rm-prompt-remove-write-protected-regular-file", + "file" => path.quote() + ) ), - _ => prompt_yes!("remove write-protected regular file {}?", path.quote()), } } @@ -90,17 +108,32 @@ fn prompt_dir_with_mode(path: &Path, mode: libc::mode_t, options: &Options) -> b (false, _, _, InteractiveMode::PromptProtected) => true, (false, false, false, InteractiveMode::Never) => true, (_, false, false, _) => prompt_yes!( - "attempt removal of inaccessible directory {}?", - path.quote() + "{}", + translate!( + "rm-prompt-attempt-remove-inaccessible-directory", + "path" => path.quote() + ) ), (_, false, true, InteractiveMode::Always) => { prompt_yes!( - "attempt removal of inaccessible directory {}?", - path.quote() + "{}", + translate!( + "rm-prompt-attempt-remove-inaccessible-directory", + "path" => path.quote() + ) ) } - (_, true, false, _) => prompt_yes!("remove write-protected directory {}?", path.quote()), - (_, _, _, InteractiveMode::Always) => prompt_yes!("remove directory {}?", path.quote()), + (_, true, false, _) => prompt_yes!( + "{}", + translate!( + "rm-prompt-remove-write-protected-directory", + "path" => path.quote() + ) + ), + (_, _, _, InteractiveMode::Always) => prompt_yes!( + "{}", + translate!("rm-prompt-remove-directory", "path" => path.quote()) + ), (_, _, _, _) => true, } } diff --git a/src/uu/rm/src/rm.rs b/src/uu/rm/src/rm.rs index a20a57d7f36..8758e8121e1 100644 --- a/src/uu/rm/src/rm.rs +++ b/src/uu/rm/src/rm.rs @@ -254,21 +254,13 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> { }, }; if options.interactive == InteractiveMode::Once && (options.recursive || files.len() > 3) { - let msg: String = format!( - "remove {} {}{}", - files.len(), - if files.len() > 1 { - "arguments" - } else { - "argument" - }, - if options.recursive { - " recursively?" - } else { - "?" - } - ); - if !prompt_yes!("{msg}") { + let prompt_key = if options.recursive { + "rm-prompt-remove-arguments-recursive" + } else { + "rm-prompt-remove-arguments" + }; + let msg = translate!(prompt_key, "count" => files.len()); + if !prompt_yes!("{}", msg) { return Ok(()); } } @@ -813,7 +805,10 @@ fn prompt_file(path: &Path, options: &Options) -> bool { if options.interactive == InteractiveMode::Always { if let Ok(metadata) = fs::symlink_metadata(path) { if metadata.is_symlink() { - return prompt_yes!("remove symbolic link {}?", path.quote()); + return prompt_yes!( + "{}", + translate!("rm-prompt-remove-symbolic-link", "file" => path.quote()) + ); } } } @@ -824,9 +819,15 @@ fn prompt_file(path: &Path, options: &Options) -> bool { if options.interactive == InteractiveMode::Always && is_writable(path) { return if metadata.len() == 0 { - prompt_yes!("remove regular empty file {}?", path.quote()) + prompt_yes!( + "{}", + translate!("rm-prompt-remove-regular-empty-file", "file" => path.quote()) + ) } else { - prompt_yes!("remove file {}?", path.quote()) + prompt_yes!( + "{}", + translate!("rm-prompt-remove-file", "file" => path.quote()) + ) }; } prompt_file_permission_readonly(path, options) @@ -838,10 +839,19 @@ fn prompt_file_permission_readonly(path: &Path, options: &Options) -> bool { (false, _, InteractiveMode::PromptProtected) => true, (_, Ok(_), _) if is_writable(path) => true, (_, Ok(metadata), _) if metadata.len() == 0 => prompt_yes!( - "remove write-protected regular empty file {}?", - path.quote() + "{}", + translate!( + "rm-prompt-remove-write-protected-regular-empty-file", + "file" => path.quote() + ) + ), + _ => prompt_yes!( + "{}", + translate!( + "rm-prompt-remove-write-protected-regular-file", + "file" => path.quote() + ) ), - _ => prompt_yes!("remove write-protected regular file {}?", path.quote()), } } @@ -874,15 +884,30 @@ fn handle_writable_directory(path: &Path, options: &Options, metadata: &Metadata (false, _, _, InteractiveMode::PromptProtected) => true, (false, false, false, InteractiveMode::Never) => true, // Don't prompt when interactive is never (_, false, false, _) => prompt_yes!( - "attempt removal of inaccessible directory {}?", - path.quote() + "{}", + translate!( + "rm-prompt-attempt-remove-inaccessible-directory", + "path" => path.quote() + ) ), (_, false, true, InteractiveMode::Always) => prompt_yes!( - "attempt removal of inaccessible directory {}?", - path.quote() + "{}", + translate!( + "rm-prompt-attempt-remove-inaccessible-directory", + "path" => path.quote() + ) + ), + (_, true, false, _) => prompt_yes!( + "{}", + translate!( + "rm-prompt-remove-write-protected-directory", + "path" => path.quote() + ) + ), + (_, _, _, InteractiveMode::Always) => prompt_yes!( + "{}", + translate!("rm-prompt-remove-directory", "path" => path.quote()) ), - (_, true, false, _) => prompt_yes!("remove write-protected directory {}?", path.quote()), - (_, _, _, InteractiveMode::Always) => prompt_yes!("remove directory {}?", path.quote()), (_, _, _, _) => true, } } @@ -896,8 +921,16 @@ fn handle_writable_directory(path: &Path, options: &Options, metadata: &Metadata let stdin_ok = options.__presume_input_tty.unwrap_or(false) || stdin().is_terminal(); match (stdin_ok, not_user_writable, options.interactive) { (false, _, InteractiveMode::PromptProtected) => true, - (_, true, _) => prompt_yes!("remove write-protected directory {}?", path.quote()), - (_, _, InteractiveMode::Always) => prompt_yes!("remove directory {}?", path.quote()), + (_, true, _) => prompt_yes!( + "{}", + translate!( + "rm-prompt-remove-write-protected-directory", + "path" => path.quote() + ) + ), + (_, _, InteractiveMode::Always) => { + prompt_yes!("{}", translate!("rm-prompt-remove-directory", "path" => path.quote())) + } (_, _, _) => true, } } @@ -907,7 +940,7 @@ fn handle_writable_directory(path: &Path, options: &Options, metadata: &Metadata #[cfg(not(unix))] fn handle_writable_directory(path: &Path, options: &Options, _metadata: &Metadata) -> bool { if options.interactive == InteractiveMode::Always { - prompt_yes!("remove directory {}?", path.quote()) + prompt_yes!("{}", translate!("rm-prompt-remove-directory", "path" => path.quote())) } else { true } @@ -948,7 +981,10 @@ fn clean_trailing_slashes(path: &Path) -> &Path { } fn prompt_descend(path: &Path) -> bool { - prompt_yes!("descend into directory {}?", path.quote()) + prompt_yes!( + "{}", + translate!("rm-prompt-descend-into-directory", "path" => path.quote()) + ) } fn normalize(path: &Path) -> PathBuf { From 735f0f0468048d03da65811fb4ea5f09612182cb Mon Sep 17 00:00:00 2001 From: mattsu Date: Thu, 25 Dec 2025 21:10:44 +0900 Subject: [PATCH 2/2] refactor(rm): format prompt_yes! macro calls for readability Break long prompt_yes! macro invocations into multiple lines in the handle_writable_directory function to improve code readability and adhere to formatting standards. No functional changes. --- src/uu/rm/src/rm.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/uu/rm/src/rm.rs b/src/uu/rm/src/rm.rs index 8758e8121e1..fc7a3cb4efc 100644 --- a/src/uu/rm/src/rm.rs +++ b/src/uu/rm/src/rm.rs @@ -929,7 +929,10 @@ fn handle_writable_directory(path: &Path, options: &Options, metadata: &Metadata ) ), (_, _, InteractiveMode::Always) => { - prompt_yes!("{}", translate!("rm-prompt-remove-directory", "path" => path.quote())) + prompt_yes!( + "{}", + translate!("rm-prompt-remove-directory", "path" => path.quote()) + ) } (_, _, _) => true, } @@ -940,7 +943,10 @@ fn handle_writable_directory(path: &Path, options: &Options, metadata: &Metadata #[cfg(not(unix))] fn handle_writable_directory(path: &Path, options: &Options, _metadata: &Metadata) -> bool { if options.interactive == InteractiveMode::Always { - prompt_yes!("{}", translate!("rm-prompt-remove-directory", "path" => path.quote())) + prompt_yes!( + "{}", + translate!("rm-prompt-remove-directory", "path" => path.quote()) + ) } else { true }