1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-27 19:17:43 +00:00

l10n: port stdbuf for translation + add french

This commit is contained in:
Sylvestre Ledru 2025-06-22 23:29:39 +02:00
parent 60bf6cbc91
commit 564daa89c8
5 changed files with 85 additions and 22 deletions

1
Cargo.lock generated
View file

@ -3498,6 +3498,7 @@ version = "0.1.0"
dependencies = [ dependencies = [
"clap", "clap",
"tempfile", "tempfile",
"thiserror 2.0.12",
"uu_stdbuf_libstdbuf", "uu_stdbuf_libstdbuf",
"uucore", "uucore",
] ]

View file

@ -23,6 +23,7 @@ clap = { workspace = true }
libstdbuf = { package = "uu_stdbuf_libstdbuf", path = "src/libstdbuf" } libstdbuf = { package = "uu_stdbuf_libstdbuf", path = "src/libstdbuf" }
tempfile = { workspace = true } tempfile = { workspace = true }
uucore = { workspace = true, features = ["parser"] } uucore = { workspace = true, features = ["parser"] }
thiserror = { workspace = true }
# "feat_external_libstdbuf": use an external libstdbuf.so for stdbuf instead of embedding it into # "feat_external_libstdbuf": use an external libstdbuf.so for stdbuf instead of embedding it into
# the stdbuf binary. # the stdbuf binary.

View file

@ -14,3 +14,18 @@ stdbuf-after-help = If MODE is 'L' the corresponding stream will be line buffere
NOTE: If COMMAND adjusts the buffering of its standard streams (tee does for e.g.) then that will override corresponding settings changed by stdbuf. NOTE: If COMMAND adjusts the buffering of its standard streams (tee does for e.g.) then that will override corresponding settings changed by stdbuf.
Also some filters (like dd and cat etc.) don't use streams for I/O, and are thus unaffected by stdbuf settings. Also some filters (like dd and cat etc.) don't use streams for I/O, and are thus unaffected by stdbuf settings.
stdbuf-help-input = adjust standard input stream buffering
stdbuf-help-output = adjust standard output stream buffering
stdbuf-help-error = adjust standard error stream buffering
stdbuf-value-mode = MODE
stdbuf-error-line-buffering-stdin-meaningless = line buffering stdin is meaningless
stdbuf-error-invalid-mode = invalid mode {$error}
stdbuf-error-value-too-large = invalid mode '{$value}': Value too large for defined data type
stdbuf-error-command-not-supported = Command not supported for this operating system!
stdbuf-error-external-libstdbuf-not-found = External libstdbuf not found at configured path: {$path}
stdbuf-error-permission-denied = failed to execute process: Permission denied
stdbuf-error-no-such-file = failed to execute process: No such file or directory
stdbuf-error-failed-to-execute = failed to execute process: {$error}
stdbuf-error-killed-by-signal = process killed by signal {$signal}

View file

@ -0,0 +1,31 @@
stdbuf-about = Exécute COMMANDE, avec des opérations de mise en mémoire tampon modifiées pour ses flux standards.
Les arguments obligatoires pour les options longues le sont aussi pour les options courtes.
stdbuf-usage = stdbuf [OPTION]... COMMANDE
stdbuf-after-help = Si MODE est 'L', le flux correspondant sera mis en mémoire tampon par ligne.
Cette option n'est pas valide avec l'entrée standard.
Si MODE est '0', le flux correspondant ne sera pas mis en mémoire tampon.
Sinon, MODE est un nombre qui peut être suivi par l'un des suivants :
KB 1000, K 1024, MB 1000*1000, M 1024*1024, et ainsi de suite pour G, T, P, E, Z, Y.
Dans ce cas, le flux correspondant sera entièrement mis en mémoire tampon avec la taille de tampon définie à MODE octets.
NOTE : Si COMMANDE ajuste la mise en mémoire tampon de ses flux standards (tee le fait par exemple), cela remplacera les paramètres correspondants modifiés par stdbuf.
De plus, certains filtres (comme dd et cat etc.) n'utilisent pas de flux pour les E/S, et ne sont donc pas affectés par les paramètres stdbuf.
stdbuf-help-input = ajuster la mise en mémoire tampon du flux d'entrée standard
stdbuf-help-output = ajuster la mise en mémoire tampon du flux de sortie standard
stdbuf-help-error = ajuster la mise en mémoire tampon du flux d'erreur standard
stdbuf-value-mode = MODE
stdbuf-error-line-buffering-stdin-meaningless = la mise en mémoire tampon par ligne de stdin n'a pas de sens
stdbuf-error-invalid-mode = mode invalide {$error}
stdbuf-error-value-too-large = mode invalide '{$value}' : Valeur trop grande pour le type de données défini
stdbuf-error-command-not-supported = Commande non prise en charge pour ce système d'exploitation !
stdbuf-error-external-libstdbuf-not-found = libstdbuf externe introuvable au chemin configuré : {$path}
stdbuf-error-permission-denied = échec de l'exécution du processus : Permission refusée
stdbuf-error-no-such-file = échec de l'exécution du processus : Aucun fichier ou répertoire de ce type
stdbuf-error-failed-to-execute = échec de l'exécution du processus : {$error}
stdbuf-error-killed-by-signal = processus tué par le signal {$signal}

View file

@ -6,16 +6,18 @@
// spell-checker:ignore (ToDO) tempdir dyld dylib optgrps libstdbuf // spell-checker:ignore (ToDO) tempdir dyld dylib optgrps libstdbuf
use clap::{Arg, ArgAction, ArgMatches, Command}; use clap::{Arg, ArgAction, ArgMatches, Command};
use std::collections::HashMap;
use std::os::unix::process::ExitStatusExt; use std::os::unix::process::ExitStatusExt;
use std::path::PathBuf; use std::path::PathBuf;
use std::process; use std::process;
use tempfile::TempDir; use tempfile::TempDir;
use tempfile::tempdir; use tempfile::tempdir;
use thiserror::Error;
use uucore::error::{FromIo, UClapError, UResult, USimpleError, UUsageError}; use uucore::error::{FromIo, UClapError, UResult, USimpleError, UUsageError};
use uucore::format_usage; use uucore::format_usage;
use uucore::parser::parse_size::parse_size_u64; use uucore::parser::parse_size::parse_size_u64;
use uucore::locale::get_message; use uucore::locale::{get_message, get_message_with_args};
mod options { mod options {
pub const INPUT: &str = "input"; pub const INPUT: &str = "input";
@ -66,7 +68,15 @@ impl TryFrom<&ArgMatches> for ProgramOptions {
} }
} }
struct ProgramOptionsError(String); #[derive(Debug, Error)]
enum ProgramOptionsError {
#[error("{}", get_message("stdbuf-error-line-buffering-stdin-meaningless"))]
LineBufferingStdinMeaningless,
#[error("{}", get_message_with_args("stdbuf-error-invalid-mode", HashMap::from([("error".to_string(), _0.clone())])))]
InvalidMode(String),
#[error("{}", get_message_with_args("stdbuf-error-value-too-large", HashMap::from([("value".to_string(), _0.clone())])))]
ValueTooLarge(String),
}
#[cfg(any( #[cfg(any(
target_os = "linux", target_os = "linux",
@ -95,7 +105,7 @@ fn preload_strings() -> UResult<(&'static str, &'static str)> {
fn preload_strings() -> UResult<(&'static str, &'static str)> { fn preload_strings() -> UResult<(&'static str, &'static str)> {
Err(USimpleError::new( Err(USimpleError::new(
1, 1,
"Command not supported for this operating system!", get_message("stdbuf-error-command-not-supported"),
)) ))
} }
@ -104,20 +114,16 @@ fn check_option(matches: &ArgMatches, name: &str) -> Result<BufferType, ProgramO
Some(value) => match value.as_str() { Some(value) => match value.as_str() {
"L" => { "L" => {
if name == options::INPUT { if name == options::INPUT {
Err(ProgramOptionsError( Err(ProgramOptionsError::LineBufferingStdinMeaningless)
"line buffering stdin is meaningless".to_string(),
))
} else { } else {
Ok(BufferType::Line) Ok(BufferType::Line)
} }
} }
x => parse_size_u64(x).map_or_else( x => parse_size_u64(x).map_or_else(
|e| Err(ProgramOptionsError(format!("invalid mode {e}"))), |e| Err(ProgramOptionsError::InvalidMode(e.to_string())),
|m| { |m| {
Ok(BufferType::Size(m.try_into().map_err(|_| { Ok(BufferType::Size(m.try_into().map_err(|_| {
ProgramOptionsError(format!( ProgramOptionsError::ValueTooLarge(x.to_string())
"invalid mode '{x}': Value too large for defined data type"
))
})?)) })?))
}, },
), ),
@ -168,9 +174,9 @@ fn get_preload_env(_tmp_dir: &TempDir) -> UResult<(String, PathBuf)> {
Err(USimpleError::new( Err(USimpleError::new(
1, 1,
format!( get_message_with_args(
"External libstdbuf not found at configured path: {}", "stdbuf-error-external-libstdbuf-not-found",
path_buf.display() HashMap::from([("path".to_string(), path_buf.display().to_string())]),
), ),
)) ))
} }
@ -179,7 +185,8 @@ fn get_preload_env(_tmp_dir: &TempDir) -> UResult<(String, PathBuf)> {
pub fn uumain(args: impl uucore::Args) -> UResult<()> { pub fn uumain(args: impl uucore::Args) -> UResult<()> {
let matches = uu_app().try_get_matches_from(args).with_exit_code(125)?; let matches = uu_app().try_get_matches_from(args).with_exit_code(125)?;
let options = ProgramOptions::try_from(&matches).map_err(|e| UUsageError::new(125, e.0))?; let options =
ProgramOptions::try_from(&matches).map_err(|e| UUsageError::new(125, e.to_string()))?;
let mut command_values = matches.get_many::<String>(options::COMMAND).unwrap(); let mut command_values = matches.get_many::<String>(options::COMMAND).unwrap();
let mut command = process::Command::new(command_values.next().unwrap()); let mut command = process::Command::new(command_values.next().unwrap());
@ -193,20 +200,25 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
set_command_env(&mut command, "_STDBUF_E", &options.stderr); set_command_env(&mut command, "_STDBUF_E", &options.stderr);
command.args(command_params); command.args(command_params);
const EXEC_ERROR: &str = "failed to execute process:";
let mut process = match command.spawn() { let mut process = match command.spawn() {
Ok(p) => p, Ok(p) => p,
Err(e) => { Err(e) => {
return match e.kind() { return match e.kind() {
std::io::ErrorKind::PermissionDenied => Err(USimpleError::new( std::io::ErrorKind::PermissionDenied => Err(USimpleError::new(
126, 126,
format!("{EXEC_ERROR} Permission denied"), get_message("stdbuf-error-permission-denied"),
)), )),
std::io::ErrorKind::NotFound => Err(USimpleError::new( std::io::ErrorKind::NotFound => Err(USimpleError::new(
127, 127,
format!("{EXEC_ERROR} No such file or directory"), get_message("stdbuf-error-no-such-file"),
)),
_ => Err(USimpleError::new(
1,
get_message_with_args(
"stdbuf-error-failed-to-execute",
HashMap::from([("error".to_string(), e.to_string())]),
),
)), )),
_ => Err(USimpleError::new(1, format!("{EXEC_ERROR} {e}"))),
}; };
} }
}; };
@ -222,7 +234,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
} }
None => Err(USimpleError::new( None => Err(USimpleError::new(
1, 1,
format!("process killed by signal {}", status.signal().unwrap()), get_message_with_args(
"stdbuf-error-killed-by-signal",
HashMap::from([("signal".to_string(), status.signal().unwrap().to_string())]),
),
)), )),
} }
} }
@ -239,7 +254,7 @@ pub fn uu_app() -> Command {
Arg::new(options::INPUT) Arg::new(options::INPUT)
.long(options::INPUT) .long(options::INPUT)
.short(options::INPUT_SHORT) .short(options::INPUT_SHORT)
.help("adjust standard input stream buffering") .help(get_message("stdbuf-help-input"))
.value_name("MODE") .value_name("MODE")
.required_unless_present_any([options::OUTPUT, options::ERROR]), .required_unless_present_any([options::OUTPUT, options::ERROR]),
) )
@ -247,7 +262,7 @@ pub fn uu_app() -> Command {
Arg::new(options::OUTPUT) Arg::new(options::OUTPUT)
.long(options::OUTPUT) .long(options::OUTPUT)
.short(options::OUTPUT_SHORT) .short(options::OUTPUT_SHORT)
.help("adjust standard output stream buffering") .help(get_message("stdbuf-help-output"))
.value_name("MODE") .value_name("MODE")
.required_unless_present_any([options::INPUT, options::ERROR]), .required_unless_present_any([options::INPUT, options::ERROR]),
) )
@ -255,7 +270,7 @@ pub fn uu_app() -> Command {
Arg::new(options::ERROR) Arg::new(options::ERROR)
.long(options::ERROR) .long(options::ERROR)
.short(options::ERROR_SHORT) .short(options::ERROR_SHORT)
.help("adjust standard error stream buffering") .help(get_message("stdbuf-help-error"))
.value_name("MODE") .value_name("MODE")
.required_unless_present_any([options::INPUT, options::OUTPUT]), .required_unless_present_any([options::INPUT, options::OUTPUT]),
) )