1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 11:37:44 +00:00

l10n: port uniq to translation + add french

This commit is contained in:
Sylvestre Ledru 2025-06-08 11:04:18 +02:00 committed by Sylvestre Ledru
parent a769fc7904
commit f3900fadde
3 changed files with 124 additions and 37 deletions

View file

@ -5,3 +5,39 @@ uniq-after-help = Filter adjacent matching lines from INPUT (or standard input),
Note: uniq does not detect repeated lines unless they are adjacent. Note: uniq does not detect repeated lines unless they are adjacent.
You may want to sort the input first, or use sort -u without uniq. You may want to sort the input first, or use sort -u without uniq.
# Help messages
uniq-help-all-repeated = print all duplicate lines. Delimiting is done with blank lines. [default: none]
uniq-help-group = show all items, separating groups with an empty line. [default: separate]
uniq-help-check-chars = compare no more than N characters in lines
uniq-help-count = prefix lines by the number of occurrences
uniq-help-ignore-case = ignore differences in case when comparing
uniq-help-repeated = only print duplicate lines
uniq-help-skip-chars = avoid comparing the first N characters
uniq-help-skip-fields = avoid comparing the first N fields
uniq-help-unique = only print unique lines
uniq-help-zero-terminated = end lines with 0 byte, not newline
# Error messages
uniq-error-write-line-terminator = Could not write line terminator
uniq-error-write-error = write error
uniq-error-invalid-argument = Invalid argument for { $opt_name }: { $arg }
uniq-error-try-help = Try 'uniq --help' for more information.
uniq-error-group-mutually-exclusive = --group is mutually exclusive with -c/-d/-D/-u
uniq-error-group-badoption = invalid argument 'badoption' for '--group'
Valid arguments are:
- 'prepend'
- 'append'
- 'separate'
- 'both'
uniq-error-all-repeated-badoption = invalid argument 'badoption' for '--all-repeated'
Valid arguments are:
- 'none'
- 'prepend'
- 'separate'
uniq-error-counts-and-repeated-meaningless = printing all duplicated lines and repeat counts is meaningless
Try 'uniq --help' for more information.
uniq-error-could-not-open = Could not open { $path }

View file

@ -0,0 +1,41 @@
uniq-about = Signaler ou omettre les lignes répétées.
uniq-usage = uniq [OPTION]... [ENTRÉE [SORTIE]]
uniq-after-help = Filtrer les lignes adjacentes correspondantes de ENTRÉE (ou l'entrée standard),
en écrivant vers SORTIE (ou la sortie standard).
Note : uniq ne détecte les lignes répétées que si elles sont adjacentes.
Vous pourriez vouloir trier l'entrée d'abord, ou utiliser sort -u sans uniq.
# Messages d'aide
uniq-help-all-repeated = afficher toutes les lignes dupliquées. La délimitation se fait avec des lignes vides. [défaut : none]
uniq-help-group = afficher tous les éléments, en séparant les groupes avec une ligne vide. [défaut : separate]
uniq-help-check-chars = comparer au maximum N caractères dans les lignes
uniq-help-count = préfixer les lignes par le nombre d'occurrences
uniq-help-ignore-case = ignorer les différences de casse lors de la comparaison
uniq-help-repeated = afficher seulement les lignes dupliquées
uniq-help-skip-chars = éviter de comparer les N premiers caractères
uniq-help-skip-fields = éviter de comparer les N premiers champs
uniq-help-unique = afficher seulement les lignes uniques
uniq-help-zero-terminated = terminer les lignes avec un octet 0, pas une nouvelle ligne
# Messages d'erreur
uniq-error-write-line-terminator = Impossible d'écrire le terminateur de ligne
uniq-error-write-error = erreur d'écriture
uniq-error-invalid-argument = Argument invalide pour { $opt_name } : { $arg }
uniq-error-try-help = Essayez 'uniq --help' pour plus d'informations.
uniq-error-group-mutually-exclusive = --group est mutuellement exclusif avec -c/-d/-D/-u
uniq-error-group-badoption = argument invalide 'badoption' pour '--group'
Arguments valides :
- 'prepend'
- 'append'
- 'separate'
- 'both'
uniq-error-all-repeated-badoption = argument invalide 'badoption' pour '--all-repeated'
Arguments valides :
- 'none'
- 'prepend'
- 'separate'
uniq-error-counts-and-repeated-meaningless = afficher toutes les lignes dupliquées et les nombres de répétitions n'a pas de sens
Essayez 'uniq --help' pour plus d'informations.
uniq-error-could-not-open = Impossible d'ouvrir { $path }

View file

@ -7,6 +7,7 @@ use clap::{
Arg, ArgAction, ArgMatches, Command, builder::ValueParser, error::ContextKind, error::Error, Arg, ArgAction, ArgMatches, Command, builder::ValueParser, error::ContextKind, error::Error,
error::ErrorKind, error::ErrorKind,
}; };
use std::collections::HashMap;
use std::ffi::{OsStr, OsString}; use std::ffi::{OsStr, OsString};
use std::fs::File; use std::fs::File;
use std::io::{BufRead, BufReader, BufWriter, Write, stdin, stdout}; use std::io::{BufRead, BufReader, BufWriter, Write, stdin, stdout};
@ -17,7 +18,7 @@ use uucore::format_usage;
use uucore::parser::shortcut_value_parser::ShortcutValueParser; use uucore::parser::shortcut_value_parser::ShortcutValueParser;
use uucore::posix::{OBSOLETE, posix_version}; use uucore::posix::{OBSOLETE, posix_version};
use uucore::locale::get_message; use uucore::locale::{get_message, get_message_with_args};
pub mod options { pub mod options {
pub static ALL_REPEATED: &str = "all-repeated"; pub static ALL_REPEATED: &str = "all-repeated";
@ -60,7 +61,7 @@ macro_rules! write_line_terminator {
($writer:expr, $line_terminator:expr) => { ($writer:expr, $line_terminator:expr) => {
$writer $writer
.write_all(&[$line_terminator]) .write_all(&[$line_terminator])
.map_err_context(|| "Could not write line terminator".to_string()) .map_err_context(|| get_message("uniq-error-write-line-terminator"))
}; };
} }
@ -108,7 +109,9 @@ impl Uniq {
{ {
write_line_terminator!(writer, line_terminator)?; write_line_terminator!(writer, line_terminator)?;
} }
writer.flush().map_err_context(|| "write error".into())?; writer
.flush()
.map_err_context(|| get_message("uniq-error-write-error"))?;
Ok(()) Ok(())
} }
@ -155,7 +158,7 @@ impl Uniq {
// Skip self.slice_start bytes (if -s was used). // Skip self.slice_start bytes (if -s was used).
// self.slice_start is how many characters to skip, but historically // self.slice_start is how many characters to skip, but historically
// uniqs `-s N` means “skip N *bytes*,” so do that literally: // uniq's `-s N` means "skip N *bytes*," so do that literally:
let skip_bytes = self.slice_start.unwrap_or(0); let skip_bytes = self.slice_start.unwrap_or(0);
let fields_to_check = if skip_bytes < fields_to_check.len() { let fields_to_check = if skip_bytes < fields_to_check.len() {
&fields_to_check[skip_bytes..] &fields_to_check[skip_bytes..]
@ -167,7 +170,7 @@ impl Uniq {
// Convert the leftover bytes to UTF-8 for character-based -w // Convert the leftover bytes to UTF-8 for character-based -w
// If invalid UTF-8, just compare them as individual bytes (fallback). // If invalid UTF-8, just compare them as individual bytes (fallback).
let Ok(string_after_skip) = std::str::from_utf8(fields_to_check) else { let Ok(string_after_skip) = std::str::from_utf8(fields_to_check) else {
// Fallback: if invalid UTF-8, treat them as single-byte “chars” // Fallback: if invalid UTF-8, treat them as single-byte "chars"
return closure(&mut fields_to_check.iter().map(|&b| b as char)); return closure(&mut fields_to_check.iter().map(|&b| b as char));
}; };
@ -225,7 +228,7 @@ impl Uniq {
} else { } else {
writer.write_all(line) writer.write_all(line)
} }
.map_err_context(|| "write error".to_string())?; .map_err_context(|| get_message("uniq-error-write-error"))?;
write_line_terminator!(writer, line_terminator) write_line_terminator!(writer, line_terminator)
} }
@ -239,7 +242,13 @@ fn opt_parsed(opt_name: &str, matches: &ArgMatches) -> UResult<Option<usize>> {
IntErrorKind::PosOverflow => Ok(Some(usize::MAX)), IntErrorKind::PosOverflow => Ok(Some(usize::MAX)),
_ => Err(USimpleError::new( _ => Err(USimpleError::new(
1, 1,
format!("Invalid argument for {opt_name}: {}", arg_str.maybe_quote()), get_message_with_args(
"uniq-error-invalid-argument",
HashMap::from([
("opt_name".to_string(), opt_name.to_string()),
("arg".to_string(), arg_str.maybe_quote().to_string()),
]),
),
)), )),
}, },
}, },
@ -509,11 +518,11 @@ fn handle_extract_obs_skip_chars(
/// for `uniq` hardcode and require the exact wording of the error message /// for `uniq` hardcode and require the exact wording of the error message
/// and it is not compatible with how Clap formats and displays those error messages. /// and it is not compatible with how Clap formats and displays those error messages.
fn map_clap_errors(clap_error: Error) -> Box<dyn UError> { fn map_clap_errors(clap_error: Error) -> Box<dyn UError> {
let footer = "Try 'uniq --help' for more information."; let footer = get_message("uniq-error-try-help");
let override_arg_conflict = let override_arg_conflict = get_message("uniq-error-group-mutually-exclusive") + "\n" + &footer;
"--group is mutually exclusive with -c/-d/-D/-u\n".to_string() + footer; let override_group_badoption = get_message("uniq-error-group-badoption") + "\n" + &footer;
let override_group_badoption = "invalid argument 'badoption' for '--group'\nValid arguments are:\n - 'prepend'\n - 'append'\n - 'separate'\n - 'both'\n".to_string() + footer; let override_all_repeated_badoption =
let override_all_repeated_badoption = "invalid argument 'badoption' for '--all-repeated'\nValid arguments are:\n - 'none'\n - 'prepend'\n - 'separate'\n".to_string() + footer; get_message("uniq-error-all-repeated-badoption") + "\n" + &footer;
let error_message = match clap_error.kind() { let error_message = match clap_error.kind() {
ErrorKind::ArgumentConflict => override_arg_conflict, ErrorKind::ArgumentConflict => override_arg_conflict,
@ -578,7 +587,7 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
if uniq.show_counts && uniq.all_repeated { if uniq.show_counts && uniq.all_repeated {
return Err(USimpleError::new( return Err(USimpleError::new(
1, 1,
"printing all duplicated lines and repeat counts is meaningless\nTry 'uniq --help' for more information.", get_message("uniq-error-counts-and-repeated-meaningless"),
)); ));
} }
@ -599,12 +608,8 @@ pub fn uu_app() -> Command {
Arg::new(options::ALL_REPEATED) Arg::new(options::ALL_REPEATED)
.short('D') .short('D')
.long(options::ALL_REPEATED) .long(options::ALL_REPEATED)
.value_parser(ShortcutValueParser::new([ .value_parser(ShortcutValueParser::new(["none", "prepend", "separate"]))
"none", .help(get_message("uniq-help-all-repeated"))
"prepend",
"separate"
]))
.help("print all duplicate lines. Delimiting is done with blank lines. [default: none]")
.value_name("delimit-method") .value_name("delimit-method")
.num_args(0..=1) .num_args(0..=1)
.default_missing_value("none") .default_missing_value("none")
@ -614,12 +619,9 @@ pub fn uu_app() -> Command {
Arg::new(options::GROUP) Arg::new(options::GROUP)
.long(options::GROUP) .long(options::GROUP)
.value_parser(ShortcutValueParser::new([ .value_parser(ShortcutValueParser::new([
"separate", "separate", "prepend", "append", "both",
"prepend",
"append",
"both",
])) ]))
.help("show all items, separating groups with an empty line. [default: separate]") .help(get_message("uniq-help-group"))
.value_name("group-method") .value_name("group-method")
.num_args(0..=1) .num_args(0..=1)
.default_missing_value("separate") .default_missing_value("separate")
@ -628,63 +630,63 @@ pub fn uu_app() -> Command {
options::REPEATED, options::REPEATED,
options::ALL_REPEATED, options::ALL_REPEATED,
options::UNIQUE, options::UNIQUE,
options::COUNT options::COUNT,
]), ]),
) )
.arg( .arg(
Arg::new(options::CHECK_CHARS) Arg::new(options::CHECK_CHARS)
.short('w') .short('w')
.long(options::CHECK_CHARS) .long(options::CHECK_CHARS)
.help("compare no more than N characters in lines") .help(get_message("uniq-help-check-chars"))
.value_name("N"), .value_name("N"),
) )
.arg( .arg(
Arg::new(options::COUNT) Arg::new(options::COUNT)
.short('c') .short('c')
.long(options::COUNT) .long(options::COUNT)
.help("prefix lines by the number of occurrences") .help(get_message("uniq-help-count"))
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
) )
.arg( .arg(
Arg::new(options::IGNORE_CASE) Arg::new(options::IGNORE_CASE)
.short('i') .short('i')
.long(options::IGNORE_CASE) .long(options::IGNORE_CASE)
.help("ignore differences in case when comparing") .help(get_message("uniq-help-ignore-case"))
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
) )
.arg( .arg(
Arg::new(options::REPEATED) Arg::new(options::REPEATED)
.short('d') .short('d')
.long(options::REPEATED) .long(options::REPEATED)
.help("only print duplicate lines") .help(get_message("uniq-help-repeated"))
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
) )
.arg( .arg(
Arg::new(options::SKIP_CHARS) Arg::new(options::SKIP_CHARS)
.short('s') .short('s')
.long(options::SKIP_CHARS) .long(options::SKIP_CHARS)
.help("avoid comparing the first N characters") .help(get_message("uniq-help-skip-chars"))
.value_name("N"), .value_name("N"),
) )
.arg( .arg(
Arg::new(options::SKIP_FIELDS) Arg::new(options::SKIP_FIELDS)
.short('f') .short('f')
.long(options::SKIP_FIELDS) .long(options::SKIP_FIELDS)
.help("avoid comparing the first N fields") .help(get_message("uniq-help-skip-fields"))
.value_name("N"), .value_name("N"),
) )
.arg( .arg(
Arg::new(options::UNIQUE) Arg::new(options::UNIQUE)
.short('u') .short('u')
.long(options::UNIQUE) .long(options::UNIQUE)
.help("only print unique lines") .help(get_message("uniq-help-unique"))
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
) )
.arg( .arg(
Arg::new(options::ZERO_TERMINATED) Arg::new(options::ZERO_TERMINATED)
.short('z') .short('z')
.long(options::ZERO_TERMINATED) .long(options::ZERO_TERMINATED)
.help("end lines with 0 byte, not newline") .help(get_message("uniq-help-zero-terminated"))
.action(ArgAction::SetTrue), .action(ArgAction::SetTrue),
) )
.arg( .arg(
@ -721,8 +723,12 @@ fn get_delimiter(matches: &ArgMatches) -> Delimiters {
fn open_input_file(in_file_name: Option<&OsStr>) -> UResult<Box<dyn BufRead>> { fn open_input_file(in_file_name: Option<&OsStr>) -> UResult<Box<dyn BufRead>> {
Ok(match in_file_name { Ok(match in_file_name {
Some(path) if path != "-" => { Some(path) if path != "-" => {
let in_file = File::open(path) let in_file = File::open(path).map_err_context(|| {
.map_err_context(|| format!("Could not open {}", path.maybe_quote()))?; get_message_with_args(
"uniq-error-could-not-open",
HashMap::from([("path".to_string(), path.maybe_quote().to_string())]),
)
})?;
Box::new(BufReader::new(in_file)) Box::new(BufReader::new(in_file))
} }
_ => Box::new(stdin().lock()), _ => Box::new(stdin().lock()),
@ -733,8 +739,12 @@ fn open_input_file(in_file_name: Option<&OsStr>) -> UResult<Box<dyn BufRead>> {
fn open_output_file(out_file_name: Option<&OsStr>) -> UResult<Box<dyn Write>> { fn open_output_file(out_file_name: Option<&OsStr>) -> UResult<Box<dyn Write>> {
Ok(match out_file_name { Ok(match out_file_name {
Some(path) if path != "-" => { Some(path) if path != "-" => {
let out_file = File::create(path) let out_file = File::create(path).map_err_context(|| {
.map_err_context(|| format!("Could not open {}", path.maybe_quote()))?; get_message_with_args(
"uniq-error-could-not-open",
HashMap::from([("path".to_string(), path.maybe_quote().to_string())]),
)
})?;
Box::new(BufWriter::new(out_file)) Box::new(BufWriter::new(out_file))
} }
_ => Box::new(stdout().lock()), _ => Box::new(stdout().lock()),