diff --git a/registry/Cargo.lock b/registry/Cargo.lock index f720b952c..d779f0ee8 100644 --- a/registry/Cargo.lock +++ b/registry/Cargo.lock @@ -61,12 +61,27 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + [[package]] name = "autocfg" version = "1.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" +[[package]] +name = "base62" +version = "2.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "10e52a7bcb1d6beebee21fb5053af9e3cbb7a7ed1a4909e534040e676437ab1f" +dependencies = [ + "rustversion", +] + [[package]] name = "bitflags" version = "1.3.2" @@ -79,6 +94,16 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8f68f53c83ab957f72c32642f3868eec03eb974d1fb82e453128456482613d36" +[[package]] +name = "bstr" +version = "1.11.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "531a9155a481e2ee699d4f98f43c0ca4ff8ee1bfd55c31e9e98fb29d2b176fe0" +dependencies = [ + "memchr", + "serde", +] + [[package]] name = "cfg-if" version = "1.0.0" @@ -131,6 +156,31 @@ version = "1.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b63caa9aa9397e2d9480a9b13673856c78d8ac123288526c37d7839f2a86990" +[[package]] +name = "crossbeam-deque" +version = "0.8.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9dd111b7b7f7d55b72c0a6ae361660ee5853c9af73f70c3c2ef6858b950e2e51" +dependencies = [ + "crossbeam-epoch", + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-epoch" +version = "0.9.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e" +dependencies = [ + "crossbeam-utils", +] + +[[package]] +name = "crossbeam-utils" +version = "0.8.21" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d0a5c400df2834b80a4c3327b3aad3a4c4cd4de0629063962b03235697506a28" + [[package]] name = "crossterm" version = "0.28.1" @@ -162,6 +212,18 @@ version = "1.0.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "feeef44e73baff3a26d371801df019877a9866a8c493d315ab00177843314f35" +[[package]] +name = "either" +version = "1.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "60b1af1c220855b6ceac025d3f6ecdd2b7c4894bfe9cd9bda4fbb4bc7c0d4cf0" + +[[package]] +name = "equivalent" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" + [[package]] name = "errno" version = "0.3.10" @@ -172,18 +234,107 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "fastrand" +version = "2.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" + +[[package]] +name = "getrandom" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43a49c392881ce6d5c3b8cb70f98717b7c07aabbdff06687b9030dbfbe2725f8" +dependencies = [ + "cfg-if", + "libc", + "wasi 0.13.3+wasi-0.2.2", + "windows-targets", +] + +[[package]] +name = "glob" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8d1add55171497b4705a648c6b583acafb01d58050a51727785f0b2c8e0a2b2" + +[[package]] +name = "globset" +version = "0.4.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "15f1ce686646e7f1e19bf7d5533fe443a45dbfb990e00629110797578b42fb19" +dependencies = [ + "aho-corasick", + "bstr", + "log", + "regex-automata 0.4.9", + "regex-syntax 0.8.5", +] + +[[package]] +name = "globwalk" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" +dependencies = [ + "bitflags 1.3.2", + "ignore", + "walkdir", +] + +[[package]] +name = "hashbrown" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289" + [[package]] name = "heck" version = "0.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" +[[package]] +name = "ignore" +version = "0.4.23" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6d89fd380afde86567dfba715db065673989d6253f42b88179abd3eae47bda4b" +dependencies = [ + "crossbeam-deque", + "globset", + "log", + "memchr", + "regex-automata 0.4.9", + "same-file", + "walkdir", + "winapi-util", +] + +[[package]] +name = "indexmap" +version = "2.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8c9c992b02b5b4c94ea26e32fe5bccb7aa7d9f390ab5c1221ff895bc7ea8b652" +dependencies = [ + "equivalent", + "hashbrown", +] + [[package]] name = "is_terminal_polyfill" version = "1.70.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" +[[package]] +name = "itertools" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1c173a5686ce8bfa551b3563d0c2170bf24ca44da99c7ca4bfdab5418c3fe57" +dependencies = [ + "either", +] + [[package]] name = "itoa" version = "1.0.14" @@ -202,6 +353,12 @@ version = "0.2.169" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b5aba8db14291edd000dfcc4d620c7ebfb122c613afb886ca8803fa4e128a20a" +[[package]] +name = "libyml" +version = "0.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "64804cc6a5042d4f05379909ba25b503ec04e2c082151d62122d5dcaa274b961" + [[package]] name = "linux-raw-sys" version = "0.4.15" @@ -247,10 +404,19 @@ checksum = "2886843bf800fba2e3377cff24abf6379b4c4d5c6681eaf9ea5b0d15090450bd" dependencies = [ "libc", "log", - "wasi", + "wasi 0.11.0+wasi-snapshot-preview1", "windows-sys 0.52.0", ] +[[package]] +name = "normpath" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c8911957c4b1549ac0dc74e30db9c8b0e66ddcd6d7acc33098f4c63a64a6d7ed" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "nu-ansi-term" version = "0.46.0" @@ -380,6 +546,7 @@ dependencies = [ "clap", "crossterm", "registry 1.3.0", + "rust-i18n", "schemars", "serde", "serde_json", @@ -403,6 +570,60 @@ dependencies = [ "windows", ] +[[package]] +name = "rust-i18n" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "039f57d22229db401af3458ca939300178e99e88b938573cea12b7c2b0f09724" +dependencies = [ + "globwalk", + "once_cell", + "regex", + "rust-i18n-macro", + "rust-i18n-support", + "smallvec", +] + +[[package]] +name = "rust-i18n-macro" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dde5c022360a2e54477882843d56b6f9bcb4bc62f504b651a2f497f0028d174f" +dependencies = [ + "glob", + "once_cell", + "proc-macro2", + "quote", + "rust-i18n-support", + "serde", + "serde_json", + "serde_yml", + "syn", +] + +[[package]] +name = "rust-i18n-support" +version = "3.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75d2844d36f62b5d6b66f9cf8f8cbdbbbdcdb5fd37a473a9cc2fb45fdcf485d2" +dependencies = [ + "arc-swap", + "base62", + "globwalk", + "itertools", + "lazy_static", + "normpath", + "once_cell", + "proc-macro2", + "regex", + "serde", + "serde_json", + "serde_yml", + "siphasher", + "toml", + "triomphe", +] + [[package]] name = "rustix" version = "0.38.44" @@ -416,12 +637,27 @@ dependencies = [ "windows-sys 0.59.0", ] +[[package]] +name = "rustversion" +version = "1.0.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f7c45b9784283f1b2e7fb61b42047c2fd678ef0960d4f6f1eba131594cc369d4" + [[package]] name = "ryu" version = "1.0.19" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ea1a2d0a644769cc99faa24c3ad26b379b786fe7c36fd3c546254801650e6dd" +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schemars" version = "0.8.21" @@ -495,6 +731,32 @@ dependencies = [ "serde", ] +[[package]] +name = "serde_spanned" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "87607cb1398ed59d48732e575a4c28a7a8ebf2454b964fe3f224f2afc07909e1" +dependencies = [ + "serde", +] + +[[package]] +name = "serde_yml" +version = "0.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "48e76bab63c3fd98d27c17f9cbce177f64a91f5e69ac04cafe04e1bb25d1dc3c" +dependencies = [ + "indexmap", + "itoa", + "libyml", + "log", + "memchr", + "ryu", + "serde", + "serde_json", + "tempfile", +] + [[package]] name = "sharded-slab" version = "0.1.7" @@ -534,12 +796,24 @@ dependencies = [ "libc", ] +[[package]] +name = "siphasher" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" + [[package]] name = "smallvec" version = "1.13.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3c5e1a9a646d36c3599cd173a41282daf47c44583ad367b8e6837255952e5c67" +[[package]] +name = "stable_deref_trait" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" + [[package]] name = "static_vcruntime" version = "2.0.0" @@ -563,6 +837,20 @@ dependencies = [ "unicode-ident", ] +[[package]] +name = "tempfile" +version = "3.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "38c246215d7d24f48ae091a2902398798e05d978b24315d6efbc00ede9a8bb91" +dependencies = [ + "cfg-if", + "fastrand", + "getrandom", + "once_cell", + "rustix", + "windows-sys 0.59.0", +] + [[package]] name = "thiserror" version = "1.0.69" @@ -593,6 +881,40 @@ dependencies = [ "once_cell", ] +[[package]] +name = "toml" +version = "0.7.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit", +] + +[[package]] +name = "toml_datetime" +version = "0.6.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0dd7358ecb8fc2f8d014bf86f6f638ce72ba252a2c3a2572f2a795f1d23efb41" +dependencies = [ + "serde", +] + +[[package]] +name = "toml_edit" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + [[package]] name = "tracing" version = "0.1.41" @@ -667,6 +989,17 @@ dependencies = [ "tracing-serde", ] +[[package]] +name = "triomphe" +version = "0.1.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ef8f7726da4807b58ea5c96fdc122f80702030edc33b35aff9190a51148ccc85" +dependencies = [ + "arc-swap", + "serde", + "stable_deref_trait", +] + [[package]] name = "unicode-ident" version = "1.0.16" @@ -691,12 +1024,31 @@ version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ba73ea9cf16a25df0c8caa16c51acb937d5712a8429db78a3ee29d5dcacd3a65" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "wasi" version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi" +version = "0.13.3+wasi-0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26816d2e1a4a36a2940b96c5296ce403917633dff8f3440e9b236ed6f6bacad2" +dependencies = [ + "wit-bindgen-rt", +] + [[package]] name = "winapi" version = "0.3.9" @@ -713,6 +1065,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -864,3 +1225,21 @@ name = "windows_x86_64_msvc" version = "0.52.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "589f6da84c646204747d1270a2a5661ea66ed1cced2631d546fdfb155959f9ec" + +[[package]] +name = "winnow" +version = "0.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f593a95398737aeed53e489c785df13f3618e41dbcd6718c6addbf1395aa6876" +dependencies = [ + "memchr", +] + +[[package]] +name = "wit-bindgen-rt" +version = "0.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3268f3d866458b787f390cf61f4bbb563b922d091359f9608842999eaee3943c" +dependencies = [ + "bitflags 2.8.0", +] diff --git a/registry/Cargo.toml b/registry/Cargo.toml index b8c8a8f64..578b16dd2 100644 --- a/registry/Cargo.toml +++ b/registry/Cargo.toml @@ -3,6 +3,11 @@ name = "registry" version = "1.0.0" edition = "2021" +[package.metadata.i18n] +available-locales = ["en-us"] +default-locale = "en-us" +load-path = "locales" + [profile.release] strip = true # optimize for size @@ -14,6 +19,7 @@ lto = true clap = { version = "4.5", features = ["derive"] } crossterm = "0.28" registry = "1.2" +rust-i18n = { version = "3.0" } schemars = "0.8" serde = "1.0" serde_json = "1.0" diff --git a/registry/locales/en-us.toml b/registry/locales/en-us.toml new file mode 100644 index 000000000..9e5040259 --- /dev/null +++ b/registry/locales/en-us.toml @@ -0,0 +1,52 @@ +_version = 1 + +[args] +about = "Manage state of Windows registry" +configAbout = "Manage registry configuration." +configArgsInputHelp = "The registry JSON input." +configArgsWhatIfHelp = "Run as a what-if operation instead of applying the registry configuration." +configGetAbout = "Retrieve registry configuration." +configSetAbout = "Apply registry configuration." +configDeleteAbout = "Delete registry configuration." +queryAbout = "Query a registry key or value." +queryArgsKeyPathHelp = "The registry key path to query." +queryArgsValueNameHelp = "The name of the value to query." +queryArgsRecurseHelp = "Recursively query subkeys." +setAbout = "Set a registry key or value." +setArgsKeyPathHelp = "The registry key path to set." +setArgsValueHelp = "The value to set." +removeAbout = "Remove a registry key or value." +removeArgsKeyPathHelp = "The registry key path to remove." +removeArgsValueNameHelp = "The name of the value to remove." +removeArgsRecurseHelp = "Recursively remove subkeys." +findAbout = "Find a registry key or value." +findArgsKeyPathHelp = "The registry key path to start find." +findArgsFindHelp = "The string to find." +findArgsRecurseHelp = "Recursively find." +findArgsKeysOnlyHelp = "Only find keys." +findArgsValuesOnlyHelp = "Only find values." +schemaAbout = "Retrieve JSON schema." + +[config] +# No localizable strings + +[error] +invalidHive = "Invalid hive" +json = "JSON" +registry = "Registry" +registryKey = "Registry key" +registryKeyNotFound = "Registry key not found" +registryValue = "Registry value" +utf16Conversion = "UTF-16 conversion failed due to interior NULL values for" +unsupportedValueDataType = "Unsupported registry value data type" + +[main] +tracingInitError = "Unable to set global default tracing subscriber. Tracing is disabled." +debugAttach = "attach debugger to pid %{pid} and press any key to continue" +debugEventReadError = "Error: Failed to read event: %{err}" +debugEventUnexpectedError = "Unexpected event: %{e:?}" + +[registry_helper] +whatIfCreateKey = "key: %{subkey} not found, would create it" +removeErrorKeyNotExist = "Key already does not exist" +removeDeletingSubKey = "Deleting subkey '%{name}' using %{parent}" diff --git a/registry/src/args.rs b/registry/src/args.rs index a0521ec9f..8da9a8cdc 100644 --- a/registry/src/args.rs +++ b/registry/src/args.rs @@ -2,9 +2,10 @@ // Licensed under the MIT License. use clap::{Parser, Subcommand}; +use rust_i18n::t; #[derive(Parser)] -#[clap(name = "registry", version = "0.0.1", about = "Manage state of Windows registry", long_about = None)] +#[clap(name = "registry", version = "0.0.1", about = t!("args.about").to_string(), long_about = None)] pub struct Arguments { #[clap(subcommand)] @@ -13,70 +14,70 @@ pub struct Arguments { #[derive(Debug, PartialEq, Eq, Subcommand)] pub enum ConfigSubCommand { - #[clap(name = "get", about = "Retrieve registry configuration.")] + #[clap(name = "get", about = t!("args.configGetAbout").to_string())] Get { - #[clap(short, long, required = true, help = "The registry JSON input.")] + #[clap(short, long, required = true, help = t!("args.configArgsInputHelp").to_string())] input: String, }, - #[clap(name = "set", about = "Apply registry configuration.")] + #[clap(name = "set", about = t!("args.configSetAbout").to_string())] Set { - #[clap(short, long, required = true, help = "The registry JSON input.")] + #[clap(short, long, required = true, help = t!("args.configArgsInputHelp").to_string())] input: String, - #[clap(short = 'w', long, help = "Run as a what-if operation instead of applying the registry configuration")] + #[clap(short = 'w', long, help = t!("args.configArgsWhatIfHelp").to_string())] what_if: bool, }, - #[clap(name = "delete", about = "Delete registry configuration.")] + #[clap(name = "delete", about = t!("args.configDeleteAbout").to_string())] Delete { - #[clap(short, long, required = true, help = "The registry JSON input.")] + #[clap(short, long, required = true, help = t!("args.configArgsInputHelp").to_string())] input: String, }, } #[derive(Debug, PartialEq, Eq, Subcommand)] pub enum SubCommand { - #[clap(name = "query", about = "Query a registry key or value.", arg_required_else_help = true)] + #[clap(name = "query", about = t!("args.queryAbout").to_string(), arg_required_else_help = true)] Query { - #[clap(short, long, required = true, help = "The registry key path to query.")] + #[clap(short, long, required = true, help = t!("args.queryArgsKeyPathHelp").to_string())] key_path: String, - #[clap(short, long, help = "The name of the value to query.")] + #[clap(short, long, help = t!("args.queryArgsValueNameHelp").to_string())] value_name: Option, - #[clap(short, long, help = "Recursively query subkeys.")] + #[clap(short, long, help = t!("args.queryArgsRecurseHelp").to_string())] recurse: bool, }, - #[clap(name = "set", about = "Set a registry key or value.")] + #[clap(name = "set", about = t!("args.setAbout").to_string())] Set { - #[clap(short, long, required = true, help = "The registry key path to set.")] + #[clap(short, long, required = true, help = t!("args.setArgsKeyPathHelp").to_string())] key_path: String, - #[clap(short, long, help = "The value to set.")] + #[clap(short, long, help = t!("args.setArgsValueHelp").to_string())] value: String, }, - #[clap(name = "remove", about = "Remove a registry key or value.", arg_required_else_help = true)] + #[clap(name = "remove", about = t!("args.removeAbout").to_string(), arg_required_else_help = true)] Remove { - #[clap(short, long, required = true, help = "The registry key path to remove.")] + #[clap(short, long, required = true, help = t!("args.removeArgsKeyPathHelp").to_string())] key_path: String, - #[clap(short, long, help = "The name of the value to remove.")] + #[clap(short, long, help = t!("args.removeArgsValueNameHelp").to_string())] value_name: Option, - #[clap(short, long, help = "Recursively remove subkeys.")] + #[clap(short, long, help = t!("args.removeArgsRecurseHelp").to_string())] recurse: bool, }, - #[clap(name = "find", about = "Find a registry key or value.", arg_required_else_help = true)] + #[clap(name = "find", about = t!("args.findAbout").to_string(), arg_required_else_help = true)] Find { - #[clap(short, long, required = true, help = "The registry key path to start find.")] + #[clap(short, long, required = true, help = t!("args.findArgsKeyPathHelp").to_string())] key_path: String, - #[clap(short, long, required = true, help = "The string to find.")] + #[clap(short, long, required = true, help = t!("args.findArgsFindHelp").to_string())] find: String, - #[clap(short, long, help = "Recursively find.")] + #[clap(short, long, help = t!("args.findArgsRecurseHelp").to_string())] recurse: bool, - #[clap(long, help = "Only find keys.")] + #[clap(long, help = t!("args.findArgsKeysOnlyHelp").to_string())] keys_only: bool, - #[clap(long, help = "Only find values.")] + #[clap(long, help = t!("args.findArgsValuesOnlyHelp").to_string())] values_only: bool, }, - #[clap(name = "config", about = "Manage registry configuration.", arg_required_else_help = true)] + #[clap(name = "config", about = t!("args.configAbout").to_string(), arg_required_else_help = true)] Config { #[clap(subcommand)] subcommand: ConfigSubCommand, }, - #[clap(name = "schema", about = "Retrieve JSON schema.")] + #[clap(name = "schema", about = t!("args.schemaAbout").to_string())] Schema, } diff --git a/registry/src/error.rs b/registry/src/error.rs index 0c768fbf4..1e171a70f 100644 --- a/registry/src/error.rs +++ b/registry/src/error.rs @@ -1,32 +1,33 @@ // Copyright (c) Microsoft Corporation. // Licensed under the MIT License. +use rust_i18n::t; use thiserror::Error; #[derive(Error, Debug)] #[allow(clippy::module_name_repetitions)] pub enum RegistryError { - #[error("Invalid hive: {0}.")] + #[error("{t}: {0}", t = t!("error.invalidHive"))] InvalidHive(String), - #[error("JSON: {0}")] + #[error("{t}: {0}", t = t!("error.json"))] Json(#[from] serde_json::Error), - #[error("Registry: {0}")] + #[error("{t}: {0}", t = t!("error.registry"))] Registry(#[from] registry::Error), - #[error("Registry key: {0}")] + #[error("{t}: {0}", t = t!("error.registryKey"))] RegistryKey(#[from] registry::key::Error), - #[error("Registry key not found: {0}")] + #[error("{t}: {0}", t = t!("error.registryKeyNotFound"))] RegistryKeyNotFound(String), - #[error("Registry value: {0}")] + #[error("{t}: {0}", t = t!("error.registryValue"))] RegistryValue(#[from] registry::value::Error), - #[error("UTF-16 conversion of {0} failed due to interior NULL values")] + #[error("{t}: {0}", t = t!("error.utf16Conversion"))] Utf16Conversion(String), - #[error("Unsupported registry value data type")] + #[error("{t}", t = t!("error.unsupportedValueDataType"))] UnsupportedValueDataType, } diff --git a/registry/src/main.rs b/registry/src/main.rs index d76663a11..5ef3ce7cd 100644 --- a/registry/src/main.rs +++ b/registry/src/main.rs @@ -6,6 +6,10 @@ use crossterm::event; #[cfg(debug_assertions)] use std::env; +// Init translations +use rust_i18n::t; +rust_i18n::i18n!("locales", fallback = "en-us"); + use args::Arguments; use clap::Parser; use registry_helper::RegistryHelper; @@ -135,19 +139,20 @@ pub fn enable_tracing() { let subscriber = tracing_subscriber::Registry::default().with(fmt).with(filter); if tracing::subscriber::set_global_default(subscriber).is_err() { - eprintln!("Unable to set global default tracing subscriber. Tracing is disabled."); + eprintln!("{}", t!("main.tracingInitError")); } } #[cfg(debug_assertions)] fn check_debug() { if env::var("DEBUG_REGISTRY").is_ok() { - eprintln!("attach debugger to pid {} and press any key to continue", std::process::id()); + eprintln!("{}", t!("main.debugAttach", pid = std::process::id())); + loop { let event = match event::read() { Ok(event) => event, Err(err) => { - eprintln!("Error: Failed to read event: {err}"); + eprintln!("{}", t!("main.debugEventReadError", "err" => err)); break; } }; @@ -157,7 +162,7 @@ fn check_debug() { break; } } else { - eprintln!("Unexpected event: {event:?}"); + eprintln!("{}", t!("main.debugEventUnexpectedError", e = event : {:?})); continue; } } diff --git a/registry/src/registry_helper.rs b/registry/src/registry_helper.rs index e7975a1bb..71adbedb3 100644 --- a/registry/src/registry_helper.rs +++ b/registry/src/registry_helper.rs @@ -2,6 +2,7 @@ // Licensed under the MIT License. use registry::{Data, Hive, RegKey, Security, key, value}; +use rust_i18n::t; use utfx::{U16CString, UCString}; use crate::config::{Metadata, Registry, RegistryValueData}; use crate::error::RegistryError; @@ -99,7 +100,7 @@ impl RegistryHelper { }; if self.what_if { - what_if_metadata.push(format!("key: {subkey} not found, would create it")); + what_if_metadata.push(t!("registry_helper.whatIfCreateKey", "subkey" => subkey).to_string()); } else { reg_key = reg_key.create(path, Security::CreateSubKey)?; @@ -185,7 +186,7 @@ impl RegistryHelper { Ok(reg_key) => reg_key, // handle NotFound error Err(RegistryError::RegistryKeyNotFound(_)) => { - eprintln!("Key already does not exist"); + eprintln!("{}", t!("registry_helper.removeErrorKeyNotExist")); return Ok(()); }, Err(e) => return Err(e), @@ -200,7 +201,8 @@ impl RegistryHelper { // get the subkey name let subkey_name = &self.config.key_path[parent_path.len() + 1..]; - eprintln!("Deleting subkey '{subkey_name}' using {parent_reg_key}"); + + eprintln!("{}", t!("registry_helper.removeDeletingSubKey", name = subkey_name, parent = parent_reg_key)); let Ok(subkey_name) = UCString::::from_str(subkey_name) else { return Err(RegistryError::Utf16Conversion("subkey_name".to_string())); };