Skip to content

Commit 19e04a2

Browse files
authored
Merge pull request #8193 from sylvestre/l10n-join
l10n: port join for translation + add french
2 parents 01ac6df + 5595d07 commit 19e04a2

3 files changed

Lines changed: 134 additions & 41 deletions

File tree

src/uu/join/locales/en-US.ftl

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,3 +3,33 @@ join-about = For each pair of input lines with identical join fields, write a li
33
44
When FILE1 or FILE2 (not both) is -, read standard input.
55
join-usage = join [OPTION]... FILE1 FILE2
6+
7+
# Join help messages
8+
join-help-a = also print unpairable lines from file FILENUM, where
9+
FILENUM is 1 or 2, corresponding to FILE1 or FILE2
10+
join-help-v = like -a FILENUM, but suppress joined output lines
11+
join-help-e = replace missing input fields with EMPTY
12+
join-help-i = ignore differences in case when comparing fields
13+
join-help-j = equivalent to '-1 FIELD -2 FIELD'
14+
join-help-o = obey FORMAT while constructing output line
15+
join-help-t = use CHAR as input and output field separator
16+
join-help-1 = join on this FIELD of file 1
17+
join-help-2 = join on this FIELD of file 2
18+
join-help-check-order = check that the input is correctly sorted, even if all input lines are pairable
19+
join-help-nocheck-order = do not check that the input is correctly sorted
20+
join-help-header = treat the first line in each file as field headers, print them without trying to pair them
21+
join-help-z = line delimiter is NUL, not newline
22+
23+
# Join error messages
24+
join-error-io = io error: { $error }
25+
join-error-non-utf8-tab = non-UTF-8 multi-byte tab
26+
join-error-unprintable-separators = unprintable field separators are only supported on unix-like platforms
27+
join-error-multi-character-tab = multi-character tab { $value }
28+
join-error-both-files-stdin = both files cannot be standard input
29+
join-error-invalid-field-specifier = invalid field specifier: { $spec }
30+
join-error-invalid-file-number = invalid file number in field spec: { $spec }
31+
join-error-invalid-file-number-simple = invalid file number: { $value }
32+
join-error-invalid-field-number = invalid field number: { $value }
33+
join-error-incompatible-fields = incompatible join fields { $field1 }, { $field2 }
34+
join-error-not-sorted = { $file }:{ $line_num }: is not sorted: { $content }
35+
join-error-input-not-sorted = input is not in sorted order

src/uu/join/locales/fr-FR.ftl

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
join-about = Pour chaque paire de lignes d'entrée avec des champs de jointure identiques, écrire une ligne
2+
sur la sortie standard. Le champ de jointure par défaut est le premier, délimité par des espaces.
3+
4+
Quand FILE1 ou FILE2 (mais pas les deux) est -, lire l'entrée standard.
5+
join-usage = join [OPTION]... FICHIER1 FICHIER2
6+
7+
# Messages d'aide de join
8+
join-help-a = afficher aussi les lignes non appariables du fichier NUMÉRO_FICHIER, où
9+
NUMÉRO_FICHIER est 1 ou 2, correspondant à FICHIER1 ou FICHIER2
10+
join-help-v = comme -a NUMÉRO_FICHIER, mais supprimer les lignes de sortie jointes
11+
join-help-e = remplacer les champs d'entrée manquants par VIDE
12+
join-help-i = ignorer les différences de casse lors de la comparaison des champs
13+
join-help-j = équivalent à '-1 CHAMP -2 CHAMP'
14+
join-help-o = obéir au FORMAT lors de la construction de la ligne de sortie
15+
join-help-t = utiliser CHAR comme séparateur de champ d'entrée et de sortie
16+
join-help-1 = joindre sur ce CHAMP du fichier 1
17+
join-help-2 = joindre sur ce CHAMP du fichier 2
18+
join-help-check-order = vérifier que l'entrée est correctement triée, même si toutes les lignes d'entrée sont appariables
19+
join-help-nocheck-order = ne pas vérifier que l'entrée est correctement triée
20+
join-help-header = traiter la première ligne de chaque fichier comme des en-têtes de champs, les imprimer sans essayer de les apparier
21+
join-help-z = le délimiteur de ligne est NUL, pas de nouvelle ligne
22+
23+
# Messages d'erreur de join
24+
join-error-io = erreur d'E/S : { $error }
25+
join-error-non-utf8-tab = tabulation multi-octets non-UTF-8
26+
join-error-unprintable-separators = les séparateurs de champs non imprimables ne sont pris en charge que sur les plateformes de type unix
27+
join-error-multi-character-tab = tabulation multi-caractères { $value }
28+
join-error-both-files-stdin = les deux fichiers ne peuvent pas être l'entrée standard
29+
join-error-invalid-field-specifier = spécificateur de champ invalide : { $spec }
30+
join-error-invalid-file-number = numéro de fichier invalide dans la spécification de champ : { $spec }
31+
join-error-invalid-file-number-simple = numéro de fichier invalide : { $value }
32+
join-error-invalid-field-number = numéro de champ invalide : { $value }
33+
join-error-incompatible-fields = champs de jointure incompatibles { $field1 }, { $field2 }
34+
join-error-not-sorted = { $file }:{ $line_num } : n'est pas trié : { $content }
35+
join-error-input-not-sorted = l'entrée n'est pas dans l'ordre trié

src/uu/join/src/join.rs

Lines changed: 69 additions & 41 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ use clap::builder::ValueParser;
99
use clap::{Arg, ArgAction, Command};
1010
use memchr::{Memchr3, memchr_iter, memmem::Finder};
1111
use std::cmp::Ordering;
12+
use std::collections::HashMap;
1213
use std::ffi::OsString;
1314
use std::fs::File;
1415
use std::io::{BufRead, BufReader, BufWriter, Split, Stdin, Write, stdin, stdout};
@@ -21,11 +22,11 @@ use uucore::error::{FromIo, UError, UResult, USimpleError, set_exit_code};
2122
use uucore::format_usage;
2223
use uucore::line_ending::LineEnding;
2324

24-
use uucore::locale::get_message;
25+
use uucore::locale::{get_message, get_message_with_args};
2526

2627
#[derive(Debug, Error)]
2728
enum JoinError {
28-
#[error("io error: {0}")]
29+
#[error("{}", get_message_with_args("join-error-io", HashMap::from([("error".to_string(), .0.to_string())])))]
2930
IOError(#[from] std::io::Error),
3031

3132
#[error("{0}")]
@@ -361,15 +362,21 @@ impl Spec {
361362
}
362363
return Err(USimpleError::new(
363364
1,
364-
format!("invalid field specifier: {}", format.quote()),
365+
get_message_with_args(
366+
"join-error-invalid-field-specifier",
367+
HashMap::from([("spec".to_string(), format.quote().to_string())]),
368+
),
365369
));
366370
}
367371
Some('1') => FileNum::File1,
368372
Some('2') => FileNum::File2,
369373
_ => {
370374
return Err(USimpleError::new(
371375
1,
372-
format!("invalid file number in field spec: {}", format.quote()),
376+
get_message_with_args(
377+
"join-error-invalid-file-number",
378+
HashMap::from([("spec".to_string(), format.quote().to_string())]),
379+
),
373380
));
374381
}
375382
};
@@ -380,7 +387,10 @@ impl Spec {
380387

381388
Err(USimpleError::new(
382389
1,
383-
format!("invalid field specifier: {}", format.quote()),
390+
get_message_with_args(
391+
"join-error-invalid-field-specifier",
392+
HashMap::from([("spec".to_string(), format.quote().to_string())]),
393+
),
384394
))
385395
}
386396
}
@@ -639,11 +649,16 @@ impl<'a> State<'a> {
639649
&& (input.check_order == CheckOrder::Enabled
640650
|| (self.has_unpaired && !self.has_failed))
641651
{
642-
let err_msg = format!(
643-
"{}:{}: is not sorted: {}",
644-
self.file_name.maybe_quote(),
645-
self.line_num,
646-
String::from_utf8_lossy(&line.string)
652+
let err_msg = get_message_with_args(
653+
"join-error-not-sorted",
654+
HashMap::from([
655+
("file".to_string(), self.file_name.maybe_quote().to_string()),
656+
("line_num".to_string(), self.line_num.to_string()),
657+
(
658+
"content".to_string(),
659+
String::from_utf8_lossy(&line.string).to_string(),
660+
),
661+
]),
647662
);
648663
// This is fatal if the check is enabled.
649664
if input.check_order == CheckOrder::Enabled {
@@ -720,11 +735,11 @@ fn parse_separator(value_os: &OsString) -> UResult<SepSetting> {
720735

721736
let Some(value) = value_os.to_str() else {
722737
#[cfg(unix)]
723-
return Err(USimpleError::new(1, "non-UTF-8 multi-byte tab"));
738+
return Err(USimpleError::new(1, get_message("join-error-non-utf8-tab")));
724739
#[cfg(not(unix))]
725740
return Err(USimpleError::new(
726741
1,
727-
"unprintable field separators are only supported on unix-like platforms",
742+
get_message("join-error-unprintable-separators"),
728743
));
729744
};
730745

@@ -733,7 +748,13 @@ fn parse_separator(value_os: &OsString) -> UResult<SepSetting> {
733748
match chars.next() {
734749
None => Ok(SepSetting::Char(value.into())),
735750
Some('0') if c == '\\' => Ok(SepSetting::Byte(0)),
736-
_ => Err(USimpleError::new(1, format!("multi-character tab {value}"))),
751+
_ => Err(USimpleError::new(
752+
1,
753+
get_message_with_args(
754+
"join-error-multi-character-tab",
755+
HashMap::from([("value".to_string(), value.to_string())]),
756+
),
757+
)),
737758
}
738759
}
739760

@@ -832,7 +853,10 @@ pub fn uumain(args: impl uucore::Args) -> UResult<()> {
832853
let file2 = matches.get_one::<String>("file2").unwrap();
833854

834855
if file1 == "-" && file2 == "-" {
835-
return Err(USimpleError::new(1, "both files cannot be standard input"));
856+
return Err(USimpleError::new(
857+
1,
858+
get_message("join-error-both-files-stdin"),
859+
));
836860
}
837861

838862
let sep = settings.separator.clone();
@@ -864,10 +888,7 @@ pub fn uu_app() -> Command {
864888
.num_args(1)
865889
.value_parser(["1", "2"])
866890
.value_name("FILENUM")
867-
.help(
868-
"also print unpairable lines from file FILENUM, where
869-
FILENUM is 1 or 2, corresponding to FILE1 or FILE2",
870-
),
891+
.help(get_message("join-help-a")),
871892
)
872893
.arg(
873894
Arg::new("v")
@@ -876,81 +897,75 @@ FILENUM is 1 or 2, corresponding to FILE1 or FILE2",
876897
.num_args(1)
877898
.value_parser(["1", "2"])
878899
.value_name("FILENUM")
879-
.help("like -a FILENUM, but suppress joined output lines"),
900+
.help(get_message("join-help-v")),
880901
)
881902
.arg(
882903
Arg::new("e")
883904
.short('e')
884905
.value_name("EMPTY")
885-
.help("replace missing input fields with EMPTY"),
906+
.help(get_message("join-help-e")),
886907
)
887908
.arg(
888909
Arg::new("i")
889910
.short('i')
890911
.long("ignore-case")
891-
.help("ignore differences in case when comparing fields")
912+
.help(get_message("join-help-i"))
892913
.action(ArgAction::SetTrue),
893914
)
894915
.arg(
895916
Arg::new("j")
896917
.short('j')
897918
.value_name("FIELD")
898-
.help("equivalent to '-1 FIELD -2 FIELD'"),
919+
.help(get_message("join-help-j")),
899920
)
900921
.arg(
901922
Arg::new("o")
902923
.short('o')
903924
.value_name("FORMAT")
904-
.help("obey FORMAT while constructing output line"),
925+
.help(get_message("join-help-o")),
905926
)
906927
.arg(
907928
Arg::new("t")
908929
.short('t')
909930
.value_name("CHAR")
910931
.value_parser(ValueParser::os_string())
911-
.help("use CHAR as input and output field separator"),
932+
.help(get_message("join-help-t")),
912933
)
913934
.arg(
914935
Arg::new("1")
915936
.short('1')
916937
.value_name("FIELD")
917-
.help("join on this FIELD of file 1"),
938+
.help(get_message("join-help-1")),
918939
)
919940
.arg(
920941
Arg::new("2")
921942
.short('2')
922943
.value_name("FIELD")
923-
.help("join on this FIELD of file 2"),
944+
.help(get_message("join-help-2")),
924945
)
925946
.arg(
926947
Arg::new("check-order")
927948
.long("check-order")
928-
.help(
929-
"check that the input is correctly sorted, \
930-
even if all input lines are pairable",
931-
)
949+
.help(get_message("join-help-check-order"))
932950
.action(ArgAction::SetTrue),
933951
)
934952
.arg(
935953
Arg::new("nocheck-order")
936954
.long("nocheck-order")
937-
.help("do not check that the input is correctly sorted")
955+
.help(get_message("join-help-nocheck-order"))
938956
.action(ArgAction::SetTrue),
939957
)
940958
.arg(
941959
Arg::new("header")
942960
.long("header")
943-
.help(
944-
"treat the first line in each file as field headers, \
945-
print them without trying to pair them",
946-
)
961+
.help(get_message("join-help-header"))
947962
.action(ArgAction::SetTrue),
948963
)
949964
.arg(
950965
Arg::new("z")
951966
.short('z')
952967
.long("zero-terminated")
953-
.help("line delimiter is NUL, not newline")
968+
.help(get_message("join-help-z"))
954969
.action(ArgAction::SetTrue),
955970
)
956971
.arg(
@@ -1082,8 +1097,9 @@ fn exec<Sep: Separator>(file1: &str, file2: &str, settings: Settings, sep: Sep)
10821097

10831098
if state1.has_failed || state2.has_failed {
10841099
eprintln!(
1085-
"{}: input is not in sorted order",
1086-
uucore::execution_phrase()
1100+
"{}: {}",
1101+
uucore::execution_phrase(),
1102+
get_message("join-error-input-not-sorted")
10871103
);
10881104
set_exit_code(1);
10891105
}
@@ -1099,7 +1115,13 @@ fn get_field_number(keys: Option<usize>, key: Option<usize>) -> UResult<usize> {
10991115
// Show zero-based field numbers as one-based.
11001116
return Err(USimpleError::new(
11011117
1,
1102-
format!("incompatible join fields {}, {}", keys + 1, key + 1),
1118+
get_message_with_args(
1119+
"join-error-incompatible-fields",
1120+
HashMap::from([
1121+
("field1".to_string(), (keys + 1).to_string()),
1122+
("field2".to_string(), (key + 1).to_string()),
1123+
]),
1124+
),
11031125
));
11041126
}
11051127
}
@@ -1118,7 +1140,10 @@ fn parse_field_number(value: &str) -> UResult<usize> {
11181140
Err(e) if e.kind() == &IntErrorKind::PosOverflow => Ok(usize::MAX),
11191141
_ => Err(USimpleError::new(
11201142
1,
1121-
format!("invalid field number: {}", value.quote()),
1143+
get_message_with_args(
1144+
"join-error-invalid-field-number",
1145+
HashMap::from([("value".to_string(), value.quote().to_string())]),
1146+
),
11221147
)),
11231148
}
11241149
}
@@ -1129,7 +1154,10 @@ fn parse_file_number(value: &str) -> UResult<FileNum> {
11291154
"2" => Ok(FileNum::File2),
11301155
value => Err(USimpleError::new(
11311156
1,
1132-
format!("invalid file number: {}", value.quote()),
1157+
get_message_with_args(
1158+
"join-error-invalid-file-number-simple",
1159+
HashMap::from([("value".to_string(), value.quote().to_string())]),
1160+
),
11331161
)),
11341162
}
11351163
}

0 commit comments

Comments
 (0)