diff --git a/build_tools/check.sh b/build_tools/check.sh index f2e3327f0..b94661a4d 100755 --- a/build_tools/check.sh +++ b/build_tools/check.sh @@ -2,17 +2,25 @@ set -ex +cleanup () { + if [ -n "$template_file" ] && [ -e "$template_file" ]; then + rm "$template_file" + fi +} + +trap cleanup EXIT INT TERM HUP + RUSTFLAGS='-D warnings'; export RUSTFLAGS RUSTDOCFLAGS='-D warnings'; export RUSTDOCFLAGS repo_root="$(dirname "$0")/.." build_dir="$repo_root/target/debug" -cargo build --workspace --all-targets +template_file=$(mktemp) +FISH_GETTEXT_EXTRACTION_FILE=$template_file cargo build --workspace --all-targets PATH="$build_dir:$PATH" "$repo_root/build_tools/style.fish" --all --check cargo clippy --workspace --all-targets cargo test --no-default-features --workspace --all-targets cargo test --doc --workspace cargo doc --workspace - -"$repo_root/tests/test_driver.py" "$build_dir" +FISH_GETTEXT_EXTRACTION_FILE=$template_file "$repo_root/tests/test_driver.py" "$build_dir" diff --git a/build_tools/fish_xgettext.fish b/build_tools/fish_xgettext.fish index d6ac9ad8d..68095c03e 100755 --- a/build_tools/fish_xgettext.fish +++ b/build_tools/fish_xgettext.fish @@ -2,6 +2,10 @@ # # Tool to generate gettext messages template file. # Writes to stdout. +# Intended to be called from `update_translations.fish`. + +argparse use-existing-template= -- $argv +or exit $status begin # Write header. This is required by msguniq. @@ -15,17 +19,25 @@ begin echo "" end - set -l rust_extraction_file (mktemp) + set -g repo_root (status dirname)/.. - # We need to build to ensure that the proc macro for extracting strings runs. - FISH_GETTEXT_EXTRACTION_FILE=$rust_extraction_file cargo check - or exit 1 + set -l rust_extraction_file + if set -l --query _flag_use_existing_template + set rust_extraction_file $_flag_use_existing_template + else + set rust_extraction_file (mktemp) + # We need to build to ensure that the proc macro for extracting strings runs. + FISH_GETTEXT_EXTRACTION_FILE=$rust_extraction_file cargo check + or exit 1 + end # Get rid of duplicates and sort. msguniq --no-wrap --strict --sort-output $rust_extraction_file or exit 1 - rm $rust_extraction_file + if not set -l --query _flag_use_existing_template + rm $rust_extraction_file + end function extract_fish_script_messages --argument-names regex @@ -47,13 +59,15 @@ begin # 5. Double quotes are escaped, such that they are not interpreted as the start or end of # a msgid. # 6. We transform the string into the format expected in a PO file. - cat share/config.fish share/completions/*.fish share/functions/*.fish | + cat $share_dir/config.fish $share_dir/completions/*.fish $share_dir/functions/*.fish | string replace --filter --regex $regex '$1' | string unescape | sort -u | sed -E -e 's_\\\\_\\\\\\\\_g' -e 's_"_\\\\"_g' -e 's_^(.*)$_msgid "\1"\nmsgstr ""\n_' end + set -g share_dir $repo_root/share + # This regex handles explicit requests to translate a message. These are more important to translate # than messages which should be implicitly translated. set -l explicit_regex '.*\( *_ (([\'"]).+?(?$template_file + set -l xgettext_args + if set -l --query _flag_use_existing_template + set xgettext_args --use-existing-template=$_flag_use_existing_template + end + $build_tools/fish_xgettext.fish $xgettext_args >$template_file or exit 1 end @@ -126,7 +139,7 @@ rm $template_file if set -g --query tmpdir rm $tmpdir/template.po - diff -ur po $tmpdir + diff -ur $po_dir $tmpdir or cleanup_exit end diff --git a/po/de.po b/po/de.po index cc454a1df..28df63a9f 100644 --- a/po/de.po +++ b/po/de.po @@ -700,6 +700,11 @@ msgstr "" msgid "%ls: expected a numeric value" msgstr "%ls: Erwartete numerischen Wert" +# +#, c-format +msgid "%ls: fish was not built with embedded files" +msgstr "" + #, c-format msgid "%ls: function name required" msgstr "%ls: Brauche Funktionsnamen" @@ -1179,6 +1184,10 @@ msgstr "Illegale Instruktion" msgid "Incomplete escape sequence '%ls'" msgstr "Unvollständige Escapesequenz '%ls'" +# +msgid "Information request" +msgstr "" + #, c-format msgid "Integer %lld in '%ls' followed by non-digit" msgstr "Ganzzahl %lld in '%ls' gefolgt von nicht-Ziffer" @@ -1709,6 +1718,10 @@ msgstr "Nicht passender Platzhalter" msgid "Unsupported use of '='. In fish, please use 'set %ls %ls'." msgstr "" +# +msgid "Unused signal" +msgstr "" + msgid "Urgent socket condition" msgstr "Vorrangige Socket-Bedingung" diff --git a/po/en.po b/po/en.po index 9e6a0c5f1..2f570a166 100644 --- a/po/en.po +++ b/po/en.po @@ -698,6 +698,11 @@ msgstr "" msgid "%ls: expected a numeric value" msgstr "%ls: expected a numeric value" +# +#, c-format +msgid "%ls: fish was not built with embedded files" +msgstr "" + #, c-format msgid "%ls: function name required" msgstr "" @@ -1177,6 +1182,9 @@ msgstr "Illegal instruction" msgid "Incomplete escape sequence '%ls'" msgstr "" +msgid "Information request" +msgstr "Information request" + #, c-format msgid "Integer %lld in '%ls' followed by non-digit" msgstr "" @@ -1707,6 +1715,9 @@ msgstr "" msgid "Unsupported use of '='. In fish, please use 'set %ls %ls'." msgstr "" +msgid "Unused signal" +msgstr "Unused signal" + msgid "Urgent socket condition" msgstr "Urgent socket condition" @@ -79398,15 +79409,9 @@ msgstr "" #~ msgid "Virtual timer expired" #~ msgstr "Virtual timer expired" -#~ msgid "Information request" -#~ msgstr "Information request" - #~ msgid "Emulator trap" #~ msgstr "Emulator trap" -#~ msgid "Unused signal" -#~ msgstr "Unused signal" - #~ msgid "Process file after the compiler reads in the standard specs file, in order to override the defaults that the gcc driver program uses when determining what switches to pass to cc1, cc1plus, as, ld, etc" #~ msgstr "Process file after the compiler reads in the standard specs file, in order to override the defaults that the gcc driver program uses when determining what switches to pass to cc1, cc1plus, as, ld, etc" diff --git a/po/fr.po b/po/fr.po index 0ff2bfffd..5381e6d7b 100644 --- a/po/fr.po +++ b/po/fr.po @@ -799,6 +799,11 @@ msgstr "" msgid "%ls: expected a numeric value" msgstr "%ls : valeur numérique attendue" +# +#, c-format +msgid "%ls: fish was not built with embedded files" +msgstr "" + #, c-format msgid "%ls: function name required" msgstr "" @@ -1278,6 +1283,9 @@ msgstr "Instruction illégale" msgid "Incomplete escape sequence '%ls'" msgstr "" +msgid "Information request" +msgstr "Demande d'information" + #, c-format msgid "Integer %lld in '%ls' followed by non-digit" msgstr "" @@ -1808,6 +1816,9 @@ msgstr "" msgid "Unsupported use of '='. In fish, please use 'set %ls %ls'." msgstr "Usage de '=' non supporté. Dans fish, veuillez utiliser 'set %ls %ls'." +msgid "Unused signal" +msgstr "Signal inutilisé" + msgid "Urgent socket condition" msgstr "Condition urgente de socket" @@ -80784,15 +80795,9 @@ msgstr "" #~ msgid "Virtual timer expired" #~ msgstr "Délai virtuel expiré" -#~ msgid "Information request" -#~ msgstr "Demande d'information" - #~ msgid "Emulator trap" #~ msgstr "Déroutement d'émulation" -#~ msgid "Unused signal" -#~ msgstr "Signal inutilisé" - #, c-format #~ msgid "getcwd() failed with errno %d/%s" #~ msgstr "getcwd() a échoué avec l’erreur %d/%s" diff --git a/po/pl.po b/po/pl.po index f98cf10ef..b34766aed 100644 --- a/po/pl.po +++ b/po/pl.po @@ -694,6 +694,11 @@ msgstr "" msgid "%ls: expected a numeric value" msgstr "%ls: oczekiwano wartości liczbowej" +# +#, c-format +msgid "%ls: fish was not built with embedded files" +msgstr "" + #, c-format msgid "%ls: function name required" msgstr "" @@ -1173,6 +1178,9 @@ msgstr "Niedozwolona instrukcja" msgid "Incomplete escape sequence '%ls'" msgstr "" +msgid "Information request" +msgstr "Żądanie informacji" + #, c-format msgid "Integer %lld in '%ls' followed by non-digit" msgstr "" @@ -1703,6 +1711,9 @@ msgstr "" msgid "Unsupported use of '='. In fish, please use 'set %ls %ls'." msgstr "Nieobsługiwane użycie '='. W fish używane jest 'set %ls %ls'." +msgid "Unused signal" +msgstr "Niewykorzystywany sygnał" + msgid "Urgent socket condition" msgstr "" @@ -79219,12 +79230,6 @@ msgstr "" #~ msgid "Could not return shell to foreground" #~ msgstr "Nie można przywrócić powłoki na pierwszy plan" -#~ msgid "Information request" -#~ msgstr "Żądanie informacji" - -#~ msgid "Unused signal" -#~ msgstr "Niewykorzystywany sygnał" - #, c-format #~ msgid "Send job %d '%ls' to background\n" #~ msgstr "Wyślij zadanie %d '%ls' w tło\n" diff --git a/po/pt_BR.po b/po/pt_BR.po index 94d31ed2c..adf6f7fcc 100644 --- a/po/pt_BR.po +++ b/po/pt_BR.po @@ -699,6 +699,11 @@ msgstr "" msgid "%ls: expected a numeric value" msgstr "%ls: esperava valor numérico" +# +#, c-format +msgid "%ls: fish was not built with embedded files" +msgstr "" + #, c-format msgid "%ls: function name required" msgstr "" @@ -1178,6 +1183,9 @@ msgstr "Instrução ilegal" msgid "Incomplete escape sequence '%ls'" msgstr "" +msgid "Information request" +msgstr "Requisição de informação" + #, c-format msgid "Integer %lld in '%ls' followed by non-digit" msgstr "" @@ -1708,6 +1716,9 @@ msgstr "" msgid "Unsupported use of '='. In fish, please use 'set %ls %ls'." msgstr "" +msgid "Unused signal" +msgstr "Sinal não utilizado" + msgid "Urgent socket condition" msgstr "Condição urgente de socket" @@ -79275,15 +79286,9 @@ msgstr "" #~ msgid "Virtual timer expired" #~ msgstr "Temporizador virtual expirado" -#~ msgid "Information request" -#~ msgstr "Requisição de informação" - #~ msgid "Emulator trap" #~ msgstr "Armadilha de emulador" -#~ msgid "Unused signal" -#~ msgstr "Sinal não utilizado" - #~ msgid "Use new incremental GNU format" #~ msgstr "Use new incremental GNU format" diff --git a/po/sv.po b/po/sv.po index c579dbd65..ea8a974ae 100644 --- a/po/sv.po +++ b/po/sv.po @@ -695,6 +695,11 @@ msgstr "" msgid "%ls: expected a numeric value" msgstr "" +# +#, c-format +msgid "%ls: fish was not built with embedded files" +msgstr "" + #, c-format msgid "%ls: function name required" msgstr "" @@ -1174,6 +1179,9 @@ msgstr "Ogiltig instruktion" msgid "Incomplete escape sequence '%ls'" msgstr "" +msgid "Information request" +msgstr "Informationsbegäran" + #, c-format msgid "Integer %lld in '%ls' followed by non-digit" msgstr "" @@ -1704,6 +1712,9 @@ msgstr "" msgid "Unsupported use of '='. In fish, please use 'set %ls %ls'." msgstr "" +msgid "Unused signal" +msgstr "Oanvänd signal" + msgid "Urgent socket condition" msgstr "Viktig socket-situation" @@ -79266,15 +79277,9 @@ msgstr "" #~ msgid "Virtual timer expired" #~ msgstr "Virtuell timer utlöst" -#~ msgid "Information request" -#~ msgstr "Informationsbegäran" - #~ msgid "Emulator trap" #~ msgstr "Emulatorfälla" -#~ msgid "Unused signal" -#~ msgstr "Oanvänd signal" - #~ msgid "Use new incremental GNU format" #~ msgstr "Använd nytt inkrementellt GNU-format" diff --git a/po/zh_CN.po b/po/zh_CN.po index 42b400ecc..fd7ab7855 100644 --- a/po/zh_CN.po +++ b/po/zh_CN.po @@ -692,6 +692,11 @@ msgstr "" msgid "%ls: expected a numeric value" msgstr "%ls: 预期数字类型值" +# +#, c-format +msgid "%ls: fish was not built with embedded files" +msgstr "" + #, c-format msgid "%ls: function name required" msgstr "%ls: 函数名称是必须的" @@ -1171,6 +1176,10 @@ msgstr "" msgid "Incomplete escape sequence '%ls'" msgstr "不完整的转义序列 '%ls'" +# +msgid "Information request" +msgstr "" + #, c-format msgid "Integer %lld in '%ls' followed by non-digit" msgstr "整数 %lld 在 '%ls' 中,后面跟随着非数字" @@ -1701,6 +1710,10 @@ msgstr "未匹配的通配符" msgid "Unsupported use of '='. In fish, please use 'set %ls %ls'." msgstr "不支持使用'='. 在fish类中,请使用'set %ls %ls'." +# +msgid "Unused signal" +msgstr "" + msgid "Urgent socket condition" msgstr "" diff --git a/src/builtins/status.rs b/src/builtins/status.rs index 13346d2f8..0b273de46 100644 --- a/src/builtins/status.rs +++ b/src/builtins/status.rs @@ -327,6 +327,11 @@ fn parse_cmd_opts( struct Docs; pub fn status(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> BuiltinResult { + localizable_consts!( + #[allow(dead_code)] + NO_EMBEDDED_FILES_MSG "%ls: fish was not built with embedded files" + ); + let cmd = args[0]; let argc = args.len(); @@ -474,10 +479,9 @@ pub fn status(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> B } #[cfg(not(feature = "embed-data"))] { - streams.err.appendln(wgettext_fmt!( - "%ls: fish was not built with embedded files", - cmd, - )); + streams + .err + .appendln(sprintf!(NO_EMBEDDED_FILES_MSG.localize(), cmd)); return Err(STATUS_CMD_ERROR); } } @@ -520,10 +524,9 @@ pub fn status(parser: &Parser, streams: &mut IoStreams, args: &mut [&wstr]) -> B } #[cfg(not(feature = "embed-data"))] { - streams.err.appendln(wgettext_fmt!( - "%ls: fish was not built with embedded files", - cmd, - )); + streams + .err + .appendln(sprintf!(NO_EMBEDDED_FILES_MSG.localize(), cmd)); return Err(STATUS_CMD_ERROR); } } diff --git a/src/signal.rs b/src/signal.rs index 45b7f4346..9aca3d42f 100644 --- a/src/signal.rs +++ b/src/signal.rs @@ -362,13 +362,16 @@ const fn new(signal: i32, name: &'static wstr, desc: LocalizableString) -> Self } macro_rules! signal_entry { - ($name:ident, $desc:expr) => { + ($name:ident, $desc:literal) => { LookupEntry::new( libc::$name, L!(stringify!($name)), localizable_string!($desc), ) }; + ($name:ident, $desc:expr) => { + LookupEntry::new(libc::$name, L!(stringify!($name)), $desc) + }; } // Lookup table used to convert between signal names and signal ids, etc. @@ -406,24 +409,41 @@ macro_rules! signal_entry { signal_entry!(SIGIOT, "Abort (Alias for SIGABRT)"), #[cfg(any(apple, bsd))] - signal_entry!(SIGEMT, "Unused signal"), + signal_entry!(SIGEMT, SIGEMT_DESC), #[cfg(any(apple, bsd))] - signal_entry!(SIGINFO, "Information request"), + signal_entry!(SIGINFO, SIGINFO_DESC), #[cfg(target_os = "linux")] - signal_entry!(SIGSTKFLT, "Stack fault"), + signal_entry!(SIGSTKFLT, SIGSTKFLT_DESC), #[cfg(target_os = "linux")] - signal_entry!(SIGIOT, "Abort (Alias for SIGABRT)"), + signal_entry!(SIGIOT, SIGIOT_DESC), #[cfg(target_os = "linux")] - signal_entry!(SIGPWR, "Power failure"), + signal_entry!(SIGPWR, SIGPWR_DESC), // TODO: determine whether SIGWIND is defined on any platform. //signal_entry!(SIGWIND, "Window size change"), ]; +localizable_consts!( + #[allow(dead_code)] + SIGEMT_DESC "Unused signal" + + #[allow(dead_code)] + SIGINFO_DESC "Information request" + + #[allow(dead_code)] + SIGSTKFLT_DESC "Stack fault" + + #[allow(dead_code)] + SIGIOT_DESC "Abort (Alias for SIGABRT)" + + #[allow(dead_code)] + SIGPWR_DESC "Power failure" +); + // Return true if two strings are equal, ignoring ASCII case. fn equals_ascii_icase(left: &wstr, right: &wstr) -> bool { if left.len() != right.len() { diff --git a/src/wutil/gettext.rs b/src/wutil/gettext.rs index 07123c884..f07600696 100644 --- a/src/wutil/gettext.rs +++ b/src/wutil/gettext.rs @@ -194,6 +194,7 @@ macro_rules! localizable_consts { )* ) => { $( + $(#[$attr])* $vis const $name: $crate::wutil::gettext::LocalizableString = localizable_string!($string); )* @@ -247,8 +248,10 @@ macro_rules! wgettext_fmt { #[serial] fn test_unlocalized() { let _cleanup = test_init(); - let s: &'static wstr = wgettext!("abc"); + let abc_str = LocalizableString::from_external_source(WString::from("abc")); + let s: &'static wstr = wgettext!(abc_str); assert_eq!(s, "abc"); - let s2: &'static wstr = wgettext!("static"); + let static_str = LocalizableString::from_external_source(WString::from("static")); + let s2: &'static wstr = wgettext!(static_str); assert_eq!(s2, "static"); } diff --git a/tests/checks/po-files-up-to-date.fish b/tests/checks/po-files-up-to-date.fish new file mode 100644 index 000000000..bbdcedd8a --- /dev/null +++ b/tests/checks/po-files-up-to-date.fish @@ -0,0 +1,19 @@ +#RUN: fish=%fish %fish %s +#REQUIRES: msguniq --help +# Compiling in this test is too expensive. +# We need the gettext template extracted from the Rust sources passed in via env var, +# in order to pass it on. +#REQUIRES: test -e "$FISH_GETTEXT_EXTRACTION_FILE" + +set -l dir (status dirname) + +# Ensure that fish is in $PATH for the translation scripts. +set -lxp PATH (path dirname $fish) + +# Using cargo in this test is expensive because $HOME is changed, +# so the entire toolchain needs to be downloaded and installed, +# followed by a clean build of the repo. +# The `--use-existing-template` argument allows using the pre-built version of the gettext template +# file. +$dir/../../build_tools/update_translations.fish --dry-run --use-existing-template=$FISH_GETTEXT_EXTRACTION_FILE +or exit 1 diff --git a/tests/checks/check-translations.fish b/tests/checks/po-files-well-formed.fish similarity index 100% rename from tests/checks/check-translations.fish rename to tests/checks/po-files-well-formed.fish