diff --git a/src/uu/numfmt/locales/en-US.ftl b/src/uu/numfmt/locales/en-US.ftl index 588a835a4..14141b9cc 100644 --- a/src/uu/numfmt/locales/en-US.ftl +++ b/src/uu/numfmt/locales/en-US.ftl @@ -34,3 +34,41 @@ numfmt-after-help = UNIT options: Optional width value (%10f) will pad output. Optional zero (%010f) width will zero pad the number. Optional negative values (%-10f) will left align. Optional precision (%.1f) will override the input determined precision. + +# Help messages +numfmt-help-delimiter = use X instead of whitespace for field delimiter +numfmt-help-field = replace the numbers in these input fields; see FIELDS below +numfmt-help-format = use printf style floating-point FORMAT; see FORMAT below for details +numfmt-help-from = auto-scale input numbers to UNITs; see UNIT below +numfmt-help-from-unit = specify the input unit size +numfmt-help-to = auto-scale output numbers to UNITs; see UNIT below +numfmt-help-to-unit = the output unit size +numfmt-help-padding = pad the output to N characters; positive N will right-align; negative N will left-align; padding is ignored if the output is wider than N; the default is to automatically pad if a whitespace is found +numfmt-help-header = print (without converting) the first N header lines; N defaults to 1 if not specified +numfmt-help-round = use METHOD for rounding when scaling +numfmt-help-suffix = print SUFFIX after each formatted number, and accept inputs optionally ending with SUFFIX +numfmt-help-invalid = set the failure mode for invalid input +numfmt-help-zero-terminated = line delimiter is NUL, not newline + +# Error messages +numfmt-error-unsupported-unit = Unsupported unit is specified +numfmt-error-invalid-unit-size = invalid unit size: { $size } +numfmt-error-invalid-padding = invalid padding value { $value } +numfmt-error-invalid-header = invalid header value { $value } +numfmt-error-grouping-cannot-be-combined-with-to = grouping cannot be combined with --to +numfmt-error-delimiter-must-be-single-character = the delimiter must be a single character +numfmt-error-invalid-number-empty = invalid number: '' +numfmt-error-invalid-suffix = invalid suffix in input: { $input } +numfmt-error-invalid-number = invalid number: { $input } +numfmt-error-missing-i-suffix = missing 'i' suffix in input: '{ $number }{ $suffix }' (e.g Ki/Mi/Gi) +numfmt-error-rejecting-suffix = rejecting suffix in input: '{ $number }{ $suffix }' (consider using --from) +numfmt-error-suffix-unsupported-for-unit = This suffix is unsupported for specified unit +numfmt-error-unit-auto-not-supported-with-to = Unit 'auto' isn't supported with --to options +numfmt-error-number-too-big = Number is too big and unsupported +numfmt-error-format-no-percent = format '{ $format }' has no % directive +numfmt-error-format-ends-in-percent = format '{ $format }' ends in % +numfmt-error-invalid-format-directive = invalid format '{ $format }', directive must be %[0]['][-][N][.][N]f +numfmt-error-invalid-format-width-overflow = invalid format '{ $format }' (width overflow) +numfmt-error-invalid-precision = invalid precision in format '{ $format }' +numfmt-error-format-too-many-percent = format '{ $format }' has too many % directives +numfmt-error-unknown-invalid-mode = Unknown invalid mode: { $mode } diff --git a/src/uu/numfmt/locales/fr-FR.ftl b/src/uu/numfmt/locales/fr-FR.ftl new file mode 100644 index 000000000..1a6294184 --- /dev/null +++ b/src/uu/numfmt/locales/fr-FR.ftl @@ -0,0 +1,74 @@ +numfmt-about = Convertir les nombres vers/depuis des chaînes lisibles par l'homme +numfmt-usage = numfmt [OPTION]... [NOMBRE]... +numfmt-after-help = Options d'UNITÉ : + + - none : aucune mise à l'échelle automatique n'est effectuée ; les suffixes déclencheront une erreur + - auto : accepter un suffixe optionnel d'une/deux lettres : + + 1K = 1000, 1Ki = 1024, 1M = 1000000, 1Mi = 1048576, + + - si : accepter un suffixe optionnel d'une lettre : + + 1K = 1000, 1M = 1000000, ... + + - iec : accepter un suffixe optionnel d'une lettre : + + 1K = 1024, 1M = 1048576, ... + + - iec-i : accepter un suffixe optionnel de deux lettres : + + 1Ki = 1024, 1Mi = 1048576, ... + + - FIELDS supporte les plages de champs de style cut(1) : + + N N-ième champ, compté à partir de 1 + N- du N-ième champ jusqu'à la fin de la ligne + N-M du N-ième au M-ième champ (inclus) + -M du premier au M-ième champ (inclus) + - tous les champs + + Plusieurs champs/plages peuvent être séparés par des virgules + + FORMAT doit être adapté pour imprimer un argument à virgule flottante %f. + Une guillemet optionnelle (%'f) activera --grouping (si supporté par la locale actuelle). + Une valeur de largeur optionnelle (%10f) remplira la sortie. Un zéro optionnel (%010f) + remplira le nombre de zéros. Des valeurs négatives optionnelles (%-10f) aligneront à gauche. + Une précision optionnelle (%.1f) remplacera la précision déterminée par l'entrée. + +# Messages d'aide +numfmt-help-delimiter = utiliser X au lieu d'espaces pour le délimiteur de champ +numfmt-help-field = remplacer les nombres dans ces champs d'entrée ; voir FIELDS ci-dessous +numfmt-help-format = utiliser le FORMAT à virgule flottante de style printf ; voir FORMAT ci-dessous pour les détails +numfmt-help-from = mettre automatiquement à l'échelle les nombres d'entrée vers les UNITÉs ; voir UNIT ci-dessous +numfmt-help-from-unit = spécifier la taille de l'unité d'entrée +numfmt-help-to = mettre automatiquement à l'échelle les nombres de sortie vers les UNITÉs ; voir UNIT ci-dessous +numfmt-help-to-unit = la taille de l'unité de sortie +numfmt-help-padding = remplir la sortie à N caractères ; N positif alignera à droite ; N négatif alignera à gauche ; le remplissage est ignoré si la sortie est plus large que N ; la valeur par défaut est de remplir automatiquement si un espace est trouvé +numfmt-help-header = imprimer (sans convertir) les N premières lignes d'en-tête ; N vaut 1 par défaut si non spécifié +numfmt-help-round = utiliser METHOD pour l'arrondi lors de la mise à l'échelle +numfmt-help-suffix = imprimer SUFFIX après chaque nombre formaté, et accepter les entrées se terminant optionnellement par SUFFIX +numfmt-help-invalid = définir le mode d'échec pour les entrées invalides +numfmt-help-zero-terminated = le délimiteur de ligne est NUL, pas retour à la ligne + +# Messages d'erreur +numfmt-error-unsupported-unit = Une unité non supportée est spécifiée +numfmt-error-invalid-unit-size = taille d'unité invalide : { $size } +numfmt-error-invalid-padding = valeur de remplissage invalide { $value } +numfmt-error-invalid-header = valeur d'en-tête invalide { $value } +numfmt-error-grouping-cannot-be-combined-with-to = le groupement ne peut pas être combiné avec --to +numfmt-error-delimiter-must-be-single-character = le délimiteur doit être un seul caractère +numfmt-error-invalid-number-empty = nombre invalide : '' +numfmt-error-invalid-suffix = suffixe invalide dans l'entrée : { $input } +numfmt-error-invalid-number = nombre invalide : { $input } +numfmt-error-missing-i-suffix = suffixe 'i' manquant dans l'entrée : '{ $number }{ $suffix }' (par ex. Ki/Mi/Gi) +numfmt-error-rejecting-suffix = rejet du suffixe dans l'entrée : '{ $number }{ $suffix }' (considérez utiliser --from) +numfmt-error-suffix-unsupported-for-unit = Ce suffixe n'est pas supporté pour l'unité spécifiée +numfmt-error-unit-auto-not-supported-with-to = L'unité 'auto' n'est pas supportée avec les options --to +numfmt-error-number-too-big = Le nombre est trop grand et non supporté +numfmt-error-format-no-percent = le format '{ $format }' n'a pas de directive % +numfmt-error-format-ends-in-percent = le format '{ $format }' se termine par % +numfmt-error-invalid-format-directive = format invalide '{ $format }', la directive doit être %[0]['][-][N][.][N]f +numfmt-error-invalid-format-width-overflow = format invalide '{ $format }' (débordement de largeur) +numfmt-error-invalid-precision = précision invalide dans le format '{ $format }' +numfmt-error-format-too-many-percent = le format '{ $format }' a trop de directives % +numfmt-error-unknown-invalid-mode = Mode invalide inconnu : { $mode } diff --git a/src/uu/numfmt/src/format.rs b/src/uu/numfmt/src/format.rs index 085beadc0..15efa3423 100644 --- a/src/uu/numfmt/src/format.rs +++ b/src/uu/numfmt/src/format.rs @@ -3,7 +3,9 @@ // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. // spell-checker:ignore powf +use std::collections::HashMap; use uucore::display::Quotable; +use uucore::locale::{get_message, get_message_with_args}; use crate::options::{NumfmtOptions, RoundMethod, TransformOptions}; use crate::units::{DisplayableSuffix, IEC_BASES, RawSuffix, Result, SI_BASES, Suffix, Unit}; @@ -63,7 +65,7 @@ impl<'a> Iterator for WhitespaceSplitter<'a> { fn parse_suffix(s: &str) -> Result<(f64, Option)> { if s.is_empty() { - return Err("invalid number: ''".to_string()); + return Err(get_message("numfmt-error-invalid-number-empty")); } let with_i = s.ends_with('i'); @@ -81,7 +83,12 @@ fn parse_suffix(s: &str) -> Result<(f64, Option)> { Some('Z') => Some((RawSuffix::Z, with_i)), Some('Y') => Some((RawSuffix::Y, with_i)), Some('0'..='9') if !with_i => None, - _ => return Err(format!("invalid suffix in input: {}", s.quote())), + _ => { + return Err(get_message_with_args( + "numfmt-error-invalid-suffix", + HashMap::from([("input".to_string(), s.quote().to_string())]), + )); + } }; let suffix_len = match suffix { @@ -90,9 +97,12 @@ fn parse_suffix(s: &str) -> Result<(f64, Option)> { Some((_, true)) => 2, }; - let number = s[..s.len() - suffix_len] - .parse::() - .map_err(|_| format!("invalid number: {}", s.quote()))?; + let number = s[..s.len() - suffix_len].parse::().map_err(|_| { + get_message_with_args( + "numfmt-error-invalid-number", + HashMap::from([("input".to_string(), s.quote().to_string())]), + ) + })?; Ok((number, suffix)) } @@ -132,15 +142,25 @@ fn remove_suffix(i: f64, s: Option, u: &Unit) -> Result { RawSuffix::Z => Ok(i * IEC_BASES[7]), RawSuffix::Y => Ok(i * IEC_BASES[8]), }, - (Some((raw_suffix, false)), &Unit::Iec(true)) => Err(format!( - "missing 'i' suffix in input: '{i}{raw_suffix:?}' (e.g Ki/Mi/Gi)" + (Some((raw_suffix, false)), &Unit::Iec(true)) => Err(get_message_with_args( + "numfmt-error-missing-i-suffix", + HashMap::from([ + ("number".to_string(), i.to_string()), + ("suffix".to_string(), format!("{raw_suffix:?}")), + ]), )), - (Some((raw_suffix, with_i)), &Unit::None) => Err(format!( - "rejecting suffix in input: '{i}{raw_suffix:?}{}' (consider using --from)", - if with_i { "i" } else { "" } + (Some((raw_suffix, with_i)), &Unit::None) => Err(get_message_with_args( + "numfmt-error-rejecting-suffix", + HashMap::from([ + ("number".to_string(), i.to_string()), + ( + "suffix".to_string(), + format!("{raw_suffix:?}{}", if with_i { "i" } else { "" }), + ), + ]), )), (None, _) => Ok(i), - (_, _) => Err("This suffix is unsupported for specified unit".to_owned()), + (_, _) => Err(get_message("numfmt-error-suffix-unsupported-for-unit")), } } @@ -218,7 +238,7 @@ fn consider_suffix( let (bases, with_i) = match *u { Unit::Si => (&SI_BASES, false), Unit::Iec(with_i) => (&IEC_BASES, with_i), - Unit::Auto => return Err("Unit 'auto' isn't supported with --to options".to_owned()), + Unit::Auto => return Err(get_message("numfmt-error-unit-auto-not-supported-with-to")), Unit::None => return Ok((n, None)), }; @@ -232,7 +252,7 @@ fn consider_suffix( _ if abs_n < bases[7] => 6, _ if abs_n < bases[8] => 7, _ if abs_n < bases[9] => 8, - _ => return Err("Number is too big and unsupported".to_string()), + _ => return Err(get_message("numfmt-error-number-too-big")), }; let v = if precision > 0 { diff --git a/src/uu/numfmt/src/numfmt.rs b/src/uu/numfmt/src/numfmt.rs index de977d035..7d362981c 100644 --- a/src/uu/numfmt/src/numfmt.rs +++ b/src/uu/numfmt/src/numfmt.rs @@ -8,6 +8,7 @@ use crate::format::format_and_print; use crate::options::*; use crate::units::{Result, Unit}; use clap::{Arg, ArgAction, ArgMatches, Command, parser::ValueSource}; +use std::collections::HashMap; use std::io::{BufRead, Error, Write}; use std::result::Result as StdResult; use std::str::FromStr; @@ -15,7 +16,7 @@ use std::str::FromStr; use units::{IEC_BASES, SI_BASES}; use uucore::display::Quotable; use uucore::error::UResult; -use uucore::locale::get_message; +use uucore::locale::{get_message, get_message_with_args}; use uucore::parser::shortcut_value_parser::ShortcutValueParser; use uucore::ranges::Range; use uucore::{format_usage, show, show_error}; @@ -97,7 +98,7 @@ fn parse_unit(s: &str) -> Result { "iec" => Ok(Unit::Iec(false)), "iec-i" => Ok(Unit::Iec(true)), "none" => Ok(Unit::None), - _ => Err("Unsupported unit is specified".to_owned()), + _ => Err(get_message("numfmt-error-unsupported-unit")), } } @@ -119,7 +120,10 @@ fn parse_unit_size(s: &str) -> Result { } } - Err(format!("invalid unit size: {}", s.quote())) + Err(get_message_with_args( + "numfmt-error-invalid-unit-size", + HashMap::from([("size".to_string(), s.quote().to_string())]), + )) } // Parses a suffix of a unit size and returns the corresponding multiplier. For example, @@ -170,7 +174,12 @@ fn parse_options(args: &ArgMatches) -> Result { 0 => Err(s), _ => Ok(n), }) - .map_err(|s| format!("invalid padding value {}", s.quote())), + .map_err(|s| { + get_message_with_args( + "numfmt-error-invalid-padding", + HashMap::from([("value".to_string(), s.quote().to_string())]), + ) + }), None => Ok(0), }?; @@ -184,7 +193,12 @@ fn parse_options(args: &ArgMatches) -> Result { 0 => Err(value), _ => Ok(n), }) - .map_err(|value| format!("invalid header value {}", value.quote())) + .map_err(|value| { + get_message_with_args( + "numfmt-error-invalid-header", + HashMap::from([("value".to_string(), value.quote().to_string())]), + ) + }) } else { Ok(0) }?; @@ -206,14 +220,18 @@ fn parse_options(args: &ArgMatches) -> Result { }; if format.grouping && to != Unit::None { - return Err("grouping cannot be combined with --to".to_string()); + return Err(get_message( + "numfmt-error-grouping-cannot-be-combined-with-to", + )); } let delimiter = args.get_one::(DELIMITER).map_or(Ok(None), |arg| { if arg.len() == 1 { Ok(Some(arg.to_string())) } else { - Err("the delimiter must be a single character".to_string()) + Err(get_message( + "numfmt-error-delimiter-must-be-single-character", + )) } })?; @@ -284,12 +302,12 @@ pub fn uu_app() -> Command { .short('d') .long(DELIMITER) .value_name("X") - .help("use X instead of whitespace for field delimiter"), + .help(get_message("numfmt-help-delimiter")), ) .arg( Arg::new(FIELD) .long(FIELD) - .help("replace the numbers in these input fields; see FIELDS below") + .help(get_message("numfmt-help-field")) .value_name("FIELDS") .allow_hyphen_values(true) .default_value(FIELD_DEFAULT), @@ -297,56 +315,48 @@ pub fn uu_app() -> Command { .arg( Arg::new(FORMAT) .long(FORMAT) - .help("use printf style floating-point FORMAT; see FORMAT below for details") + .help(get_message("numfmt-help-format")) .value_name("FORMAT") .allow_hyphen_values(true), ) .arg( Arg::new(FROM) .long(FROM) - .help("auto-scale input numbers to UNITs; see UNIT below") + .help(get_message("numfmt-help-from")) .value_name("UNIT") .default_value(FROM_DEFAULT), ) .arg( Arg::new(FROM_UNIT) .long(FROM_UNIT) - .help("specify the input unit size") + .help(get_message("numfmt-help-from-unit")) .value_name("N") .default_value(FROM_UNIT_DEFAULT), ) .arg( Arg::new(TO) .long(TO) - .help("auto-scale output numbers to UNITs; see UNIT below") + .help(get_message("numfmt-help-to")) .value_name("UNIT") .default_value(TO_DEFAULT), ) .arg( Arg::new(TO_UNIT) .long(TO_UNIT) - .help("the output unit size") + .help(get_message("numfmt-help-to-unit")) .value_name("N") .default_value(TO_UNIT_DEFAULT), ) .arg( Arg::new(PADDING) .long(PADDING) - .help( - "pad the output to N characters; positive N will \ - right-align; negative N will left-align; padding is \ - ignored if the output is wider than N; the default is \ - to automatically pad if a whitespace is found", - ) + .help(get_message("numfmt-help-padding")) .value_name("N"), ) .arg( Arg::new(HEADER) .long(HEADER) - .help( - "print (without converting) the first N header lines; \ - N defaults to 1 if not specified", - ) + .help(get_message("numfmt-help-header")) .num_args(..=1) .value_name("N") .default_missing_value(HEADER_DEFAULT) @@ -355,7 +365,7 @@ pub fn uu_app() -> Command { .arg( Arg::new(ROUND) .long(ROUND) - .help("use METHOD for rounding when scaling") + .help(get_message("numfmt-help-round")) .value_name("METHOD") .default_value("from-zero") .value_parser(ShortcutValueParser::new([ @@ -369,16 +379,13 @@ pub fn uu_app() -> Command { .arg( Arg::new(SUFFIX) .long(SUFFIX) - .help( - "print SUFFIX after each formatted number, and accept \ - inputs optionally ending with SUFFIX", - ) + .help(get_message("numfmt-help-suffix")) .value_name("SUFFIX"), ) .arg( Arg::new(INVALID) .long(INVALID) - .help("set the failure mode for invalid input") + .help(get_message("numfmt-help-invalid")) .default_value("abort") .value_parser(["abort", "fail", "warn", "ignore"]) .value_name("INVALID"), @@ -387,7 +394,7 @@ pub fn uu_app() -> Command { Arg::new(ZERO_TERMINATED) .long(ZERO_TERMINATED) .short('z') - .help("line delimiter is NUL, not newline") + .help(get_message("numfmt-help-zero-terminated")) .action(ArgAction::SetTrue), ) .arg(Arg::new(NUMBER).hide(true).action(ArgAction::Append)) @@ -465,9 +472,9 @@ mod tests { let result_display = format!("{result}"); assert_eq!( result_debug, - "FormattingError(\"invalid suffix in input: 'hello'\")" + "FormattingError(\"numfmt-error-invalid-suffix\")" ); - assert_eq!(result_display, "invalid suffix in input: 'hello'"); + assert_eq!(result_display, "numfmt-error-invalid-suffix"); assert_eq!(result.code(), 2); } diff --git a/src/uu/numfmt/src/options.rs b/src/uu/numfmt/src/options.rs index 72cfe2269..6f5bd7ff9 100644 --- a/src/uu/numfmt/src/options.rs +++ b/src/uu/numfmt/src/options.rs @@ -2,9 +2,11 @@ // // For the full copyright and license information, please view the LICENSE // file that was distributed with this source code. +use std::collections::HashMap; use std::str::FromStr; use crate::units::Unit; +use uucore::locale::get_message_with_args; use uucore::ranges::Range; pub const DELIMITER: &str = "delimiter"; @@ -145,9 +147,15 @@ impl FromStr for FormatOptions { if iter.peek().is_none() { return if options.prefix == s { - Err(format!("format '{s}' has no % directive")) + Err(get_message_with_args( + "numfmt-error-format-no-percent", + HashMap::from([("format".to_string(), s.to_string())]), + )) } else { - Err(format!("format '{s}' ends in %")) + Err(get_message_with_args( + "numfmt-error-format-ends-in-percent", + HashMap::from([("format".to_string(), s.to_string())]), + )) }; } @@ -167,8 +175,9 @@ impl FromStr for FormatOptions { match iter.peek() { Some(c) if c.is_ascii_digit() => padding.push('-'), _ => { - return Err(format!( - "invalid format '{s}', directive must be %[0]['][-][N][.][N]f" + return Err(get_message_with_args( + "numfmt-error-invalid-format-directive", + HashMap::from([("format".to_string(), s.to_string())]), )); } } @@ -187,7 +196,10 @@ impl FromStr for FormatOptions { if let Ok(p) = padding.parse() { options.padding = Some(p); } else { - return Err(format!("invalid format '{s}' (width overflow)")); + return Err(get_message_with_args( + "numfmt-error-invalid-format-width-overflow", + HashMap::from([("format".to_string(), s.to_string())]), + )); } } @@ -195,7 +207,10 @@ impl FromStr for FormatOptions { iter.next(); if matches!(iter.peek(), Some(' ' | '+' | '-')) { - return Err(format!("invalid precision in format '{s}'")); + return Err(get_message_with_args( + "numfmt-error-invalid-precision", + HashMap::from([("format".to_string(), s.to_string())]), + )); } while let Some(c) = iter.peek() { @@ -212,15 +227,19 @@ impl FromStr for FormatOptions { } else if let Ok(p) = precision.parse() { options.precision = Some(p); } else { - return Err(format!("invalid precision in format '{s}'")); + return Err(get_message_with_args( + "numfmt-error-invalid-precision", + HashMap::from([("format".to_string(), s.to_string())]), + )); } } if let Some('f') = iter.peek() { iter.next(); } else { - return Err(format!( - "invalid format '{s}', directive must be %[0]['][-][N][.][N]f" + return Err(get_message_with_args( + "numfmt-error-invalid-format-directive", + HashMap::from([("format".to_string(), s.to_string())]), )); } @@ -235,7 +254,10 @@ impl FromStr for FormatOptions { } iter.next(); } else { - return Err(format!("format '{s}' has too many % directives")); + return Err(get_message_with_args( + "numfmt-error-format-too-many-percent", + HashMap::from([("format".to_string(), s.to_string())]), + )); } } @@ -252,7 +274,10 @@ impl FromStr for InvalidModes { "fail" => Ok(Self::Fail), "warn" => Ok(Self::Warn), "ignore" => Ok(Self::Ignore), - unknown => Err(format!("Unknown invalid mode: {unknown}")), + unknown => Err(get_message_with_args( + "numfmt-error-unknown-invalid-mode", + HashMap::from([("mode".to_string(), unknown.to_string())]), + )), } } }