diff --git a/Cargo.lock b/Cargo.lock index f5243dd9..be50129b 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -171,22 +171,34 @@ dependencies = [ ] [[package]] -name = "base62" -version = "2.0.3" +name = "basic-toml" +version = "0.1.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48fa474cf7492f9a299ba6019fb99ec673e1739556d48e8a90eabaea282ef0e4" +checksum = "823388e228f614e9558c6804262db37960ec8821856535f5c3f59913140558f8" +dependencies = [ + "serde", +] [[package]] name = "bitflags" -version = "1.3.2" +version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a" +checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" [[package]] -name = "bitflags" -version = "2.6.0" +name = "block" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b048fb63fd8b5923fc5aa7b340d8e156aec7ec02f0c78fa8a6ddc2613f6f71de" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + +[[package]] +name = "block-buffer" +version = "0.10.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3078c7629b62d3f0439517fa394996acacc5cbc91c5a20d8c658e77abd503a71" +dependencies = [ + "generic-array", +] [[package]] name = "blocking" @@ -201,16 +213,6 @@ dependencies = [ "piper", ] -[[package]] -name = "bstr" -version = "1.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a68f1f47cdf0ec8ee4b941b2eee2a80cb796db73118c0dd09ac63fbe405be22" -dependencies = [ - "memchr", - "serde", -] - [[package]] name = "bumpalo" version = "3.16.0" @@ -425,6 +427,15 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" +[[package]] +name = "cpufeatures" +version = "0.2.16" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "16b80225097f2e5ae4e7179dd2266824648f3e2f49d9134d584b76389d31c4c3" +dependencies = [ + "libc", +] + [[package]] name = "crossbeam" version = "0.8.4" @@ -487,7 +498,7 @@ version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "829d955a0bb380ef178a640b91779e3987da38c9aea133b20614cfed8cdea9c6" dependencies = [ - "bitflags 2.6.0", + "bitflags", "crossterm_winapi", "mio", "parking_lot", @@ -506,6 +517,16 @@ dependencies = [ "winapi", ] +[[package]] +name = "crypto-common" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" +dependencies = [ + "generic-array", + "typenum", +] + [[package]] name = "csv" version = "1.3.1" @@ -562,6 +583,20 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "dashmap" +version = "6.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5041cc499144891f3790297212f32a74fb938e5136a14943f338ef9e0ae276cf" +dependencies = [ + "cfg-if", + "crossbeam-utils", + "hashbrown 0.14.5", + "lock_api", + "once_cell", + "parking_lot_core", +] + [[package]] name = "data-encoding" version = "2.6.0" @@ -594,6 +629,16 @@ version = "0.1.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "56254986775e3233ffa9c4d7d3faaf6d36a2c09d30b20687e9f88bc8bafc16c8" +[[package]] +name = "digest" +version = "0.10.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" +dependencies = [ + "block-buffer", + "crypto-common", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -719,12 +764,65 @@ version = "2.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37909eebbb50d72f9059c3b6d82c0463f2ff062c9e95845c43a6c9c0355411be" +[[package]] +name = "find-crate" +version = "0.6.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "59a98bbaacea1c0eb6a0876280051b892eb73594fd90cf3b20e9c817029c57d2" +dependencies = [ + "toml 0.5.11", +] + [[package]] name = "fixedbitset" version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0ce7134b9999ecaf8bcd65542e436736ef32ddca1b3e06094cb6ec5755203b80" +[[package]] +name = "fluent" +version = "0.16.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bb74634707bebd0ce645a981148e8fb8c7bccd4c33c652aeffd28bf2f96d555a" +dependencies = [ + "fluent-bundle", + "unic-langid", +] + +[[package]] +name = "fluent-bundle" +version = "0.15.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7fe0a21ee80050c678013f82edf4b705fe2f26f1f9877593d13198612503f493" +dependencies = [ + "fluent-langneg", + "fluent-syntax", + "intl-memoizer", + "intl_pluralrules", + "rustc-hash", + "self_cell 0.10.3", + "smallvec", + "unic-langid", +] + +[[package]] +name = "fluent-langneg" +version = "0.13.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4ad0989667548f06ccd0e306ed56b61bd4d35458d54df5ec7587c0e8ed5e94" +dependencies = [ + "unic-langid", +] + +[[package]] +name = "fluent-syntax" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d" +dependencies = [ + "thiserror 1.0.69", +] + [[package]] name = "fnv" version = "1.0.7" @@ -851,6 +949,16 @@ dependencies = [ "slab", ] +[[package]] +name = "generic-array" +version = "0.14.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "85649ca51fd72272d7821adaf274ad91c288277713d9c18820d8499a7ff69e9a" +dependencies = [ + "typenum", + "version_check", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -869,34 +977,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "07e28edb80900c19c28f1072f2e8aeca7fa06b23cd4169cefe1af5aa3260783f" [[package]] -name = "glob" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b" - -[[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" +name = "hashbrown" +version = "0.14.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "93e3af942408868f6934a7b85134a3230832b9977cf66125df2f9edcfce4ddcc" -dependencies = [ - "bitflags 1.3.2", - "ignore", - "walkdir", -] +checksum = "e5274423e17b7c9fc20b6e7e208532f9b19825d82dfd615708b70edd83df41f1" [[package]] name = "hashbrown" @@ -1000,6 +1084,76 @@ version = "2.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a3a5bfb195931eeb336b2a7b4d761daec841b97f947d34394601737a7bba5e4" +[[package]] +name = "i18n-config" +version = "0.4.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e88074831c0be5b89181b05e6748c4915f77769ecc9a4c372f88b169a8509c9" +dependencies = [ + "basic-toml", + "log", + "serde", + "serde_derive", + "thiserror 1.0.69", + "unic-langid", +] + +[[package]] +name = "i18n-embed" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a7839d8c7bb8da7bd58c1112d3a1aeb7f178ff3df4ae87783e758ca3bfb750b7" +dependencies = [ + "arc-swap", + "fluent", + "fluent-langneg", + "fluent-syntax", + "i18n-embed-impl", + "intl-memoizer", + "lazy_static", + "locale_config", + "log", + "parking_lot", + "rust-embed", + "thiserror 1.0.69", + "unic-langid", + "walkdir", +] + +[[package]] +name = "i18n-embed-fl" +version = "0.9.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f6e9571c3cba9eba538eaa5ee40031b26debe76f0c7e17bafc97ea57a76cd82e" +dependencies = [ + "dashmap", + "find-crate", + "fluent", + "fluent-syntax", + "i18n-config", + "i18n-embed", + "lazy_static", + "proc-macro-error2", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.90", + "unic-langid", +] + +[[package]] +name = "i18n-embed-impl" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f2cc0e0523d1fe6fc2c6f66e5038624ea8091b3e7748b5e8e0c84b1698db6c2" +dependencies = [ + "find-crate", + "i18n-config", + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "iana-time-zone" version = "0.1.61" @@ -1168,22 +1322,6 @@ dependencies = [ "icu_properties", ] -[[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.0" @@ -1191,7 +1329,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "62f822373a4fe84d4bb149bf54e584a7f4abec90e072ed49cda0edea5b95471f" dependencies = [ "equivalent", - "hashbrown", + "hashbrown 0.15.2", ] [[package]] @@ -1227,6 +1365,25 @@ dependencies = [ "syn 2.0.90", ] +[[package]] +name = "intl-memoizer" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe22e020fce238ae18a6d5d8c502ee76a52a6e880d99477657e6acc30ec57bda" +dependencies = [ + "type-map", + "unic-langid", +] + +[[package]] +name = "intl_pluralrules" +version = "7.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972" +dependencies = [ + "unic-langid", +] + [[package]] name = "ipconfig" version = "0.3.2" @@ -1260,15 +1417,6 @@ 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 = "itertools" version = "0.13.0" @@ -1316,12 +1464,6 @@ dependencies = [ "windows-targets 0.52.6", ] -[[package]] -name = "libyml" -version = "0.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64804cc6a5042d4f05379909ba25b503ec04e2c082151d62122d5dcaa274b961" - [[package]] name = "linked-hash-map" version = "0.5.6" @@ -1340,6 +1482,19 @@ version = "0.7.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4ee93343901ab17bd981295f2cf0026d4ad018c7c31ba84549a4ddbb47a45104" +[[package]] +name = "locale_config" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d2c35b16f4483f6c26f0e4e9550717a2f6575bcd6f12a53ff0c490a94a6934" +dependencies = [ + "lazy_static", + "objc", + "objc-foundation", + "regex", + "winapi", +] + [[package]] name = "lock_api" version = "0.4.12" @@ -1362,7 +1517,7 @@ version = "0.12.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38" dependencies = [ - "hashbrown", + "hashbrown 0.15.2", ] [[package]] @@ -1374,6 +1529,15 @@ dependencies = [ "linked-hash-map", ] +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "match_cfg" version = "0.1.0" @@ -1469,22 +1633,13 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "71e2746dc3a24dd78b3cfcb7be93368c6de9963d30f43a6a73998a9cf4b17b46" dependencies = [ - "bitflags 2.6.0", + "bitflags", "cfg-if", "cfg_aliases", "libc", "memoffset", ] -[[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" @@ -1504,6 +1659,35 @@ dependencies = [ "autocfg", ] +[[package]] +name = "objc" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1" +dependencies = [ + "malloc_buf", +] + +[[package]] +name = "objc-foundation" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9" +dependencies = [ + "block", + "objc", + "objc_id", +] + +[[package]] +name = "objc_id" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" +dependencies = [ + "objc", +] + [[package]] name = "object" version = "0.36.5" @@ -1644,6 +1828,28 @@ dependencies = [ "yansi", ] +[[package]] +name = "proc-macro-error-attr2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "96de42df36bb9bba5542fe9f1a054b8cc87e172759a1868aa05c1f3acc89dfc5" +dependencies = [ + "proc-macro2", + "quote", +] + +[[package]] +name = "proc-macro-error2" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "11ec05c52be0a07b08061f7dd003e7d7092e0472bc731b4af7bb1ef876109802" +dependencies = [ + "proc-macro-error-attr2", + "proc-macro2", + "quote", + "syn 2.0.90", +] + [[package]] name = "proc-macro2" version = "1.0.92" @@ -1704,13 +1910,13 @@ version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "eabd94c2f37801c20583fc49dd5cd6b0ba68c716787c2dd6ed18571e1e63117b" dependencies = [ - "bitflags 2.6.0", + "bitflags", "cassowary", "compact_str", "crossterm", "indoc", "instability", - "itertools 0.13.0", + "itertools", "lru", "paste", "strum", @@ -1725,7 +1931,7 @@ version = "0.5.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9b6dfecf2c74bce2466cabf93f6664d6998a69eb21e39f4207930065b27b771f" dependencies = [ - "bitflags 2.6.0", + "bitflags", ] [[package]] @@ -1789,57 +1995,37 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88f8660c1ff60292143c98d08fc6e2f654d722db50410e3f3797d40baaf9d8f3" [[package]] -name = "rust-i18n" -version = "3.1.2" +name = "rust-embed" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "039f57d22229db401af3458ca939300178e99e88b938573cea12b7c2b0f09724" +checksum = "fa66af4a4fdd5e7ebc276f115e895611a34739a9c1c01028383d612d550953c0" dependencies = [ - "globwalk", - "once_cell", - "regex", - "rust-i18n-macro", - "rust-i18n-support", - "smallvec", + "rust-embed-impl", + "rust-embed-utils", + "walkdir", ] [[package]] -name = "rust-i18n-macro" -version = "3.1.2" +name = "rust-embed-impl" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dde5c022360a2e54477882843d56b6f9bcb4bc62f504b651a2f497f0028d174f" +checksum = "6125dbc8867951125eec87294137f4e9c2c96566e61bf72c45095a7c77761478" dependencies = [ - "glob", - "once_cell", "proc-macro2", "quote", - "rust-i18n-support", - "serde", - "serde_json", - "serde_yml", + "rust-embed-utils", "syn 2.0.90", + "walkdir", ] [[package]] -name = "rust-i18n-support" -version = "3.1.2" +name = "rust-embed-utils" +version = "8.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "75d2844d36f62b5d6b66f9cf8f8cbdbbbdcdb5fd37a473a9cc2fb45fdcf485d2" +checksum = "2e5347777e9aacb56039b0e1f28785929a8a3b709e87482e7442c72e7c12529d" dependencies = [ - "arc-swap", - "base62", - "globwalk", - "itertools 0.11.0", - "lazy_static", - "normpath", - "once_cell", - "proc-macro2", - "regex", - "serde", - "serde_json", - "serde_yml", - "siphasher", - "toml 0.7.8", - "triomphe", + "sha2", + "walkdir", ] [[package]] @@ -1848,13 +2034,19 @@ version = "0.1.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "719b953e2095829ee67db738b3bfa9fa368c94900df327b3f07fe6e794d2fe1f" +[[package]] +name = "rustc-hash" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" + [[package]] name = "rustix" version = "0.38.42" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f93dc38ecbab2eb790ff964bb77fa94faf256fd3e73285fd7ba0903b76bedb85" dependencies = [ - "bitflags 2.6.0", + "bitflags", "errno", "libc", "linux-raw-sys", @@ -1888,6 +2080,21 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" +[[package]] +name = "self_cell" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" +dependencies = [ + "self_cell 1.1.0", +] + +[[package]] +name = "self_cell" +version = "1.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c2fdfc24bc566f839a2da4c4295b82db7d25a24253867d5c64355abb5799bdbe" + [[package]] name = "serde" version = "1.0.216" @@ -1953,20 +2160,14 @@ dependencies = [ ] [[package]] -name = "serde_yml" -version = "0.0.11" +name = "sha2" +version = "0.10.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e76bab63c3fd98d27c17f9cbce177f64a91f5e69ac04cafe04e1bb25d1dc3c" +checksum = "793db75ad2bcafc3ffa7c68b215fee268f537982cd901d132f89c6343f3a3dc8" dependencies = [ - "indexmap", - "itoa", - "libyml", - "log", - "memchr", - "ryu", - "serde", - "serde_json", - "tempfile", + "cfg-if", + "cpufeatures", + "digest", ] [[package]] @@ -2020,12 +2221,6 @@ version = "2.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1de1d4f81173b03af4c0cbed3c898f6bff5b870e4a7f5d6f4057d62a7a4b686e" -[[package]] -name = "siphasher" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56199f7ddabf13fe5074ce809e7d3f42b42ae711800501b5b16ea82ad029c39d" - [[package]] name = "slab" version = "0.4.9" @@ -2124,28 +2319,6 @@ dependencies = [ "syn 2.0.90", ] -[[package]] -name = "sys-locale" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" -dependencies = [ - "libc", -] - -[[package]] -name = "tempfile" -version = "3.14.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28cce251fcbc87fac86a866eeb0d6c2d536fc16d06f184bb61aeae11aa4cee0c" -dependencies = [ - "cfg-if", - "fastrand", - "once_cell", - "rustix", - "windows-sys 0.59.0", -] - [[package]] name = "terminal_size" version = "0.4.1" @@ -2314,14 +2487,11 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.8" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" dependencies = [ "serde", - "serde_spanned", - "toml_datetime", - "toml_edit 0.19.15", ] [[package]] @@ -2333,7 +2503,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit 0.22.22", + "toml_edit", ] [[package]] @@ -2345,19 +2515,6 @@ 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 0.5.40", -] - [[package]] name = "toml_edit" version = "0.22.22" @@ -2368,7 +2525,7 @@ dependencies = [ "serde", "serde_spanned", "toml_datetime", - "winnow 0.6.20", + "winnow", ] [[package]] @@ -2377,7 +2534,7 @@ version = "0.1.0" dependencies = [ "anyhow", "clap", - "itertools 0.13.0", + "itertools", "trippy", ] @@ -2466,17 +2623,6 @@ 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 = "trippy" version = "0.13.0-dev" @@ -2495,12 +2641,12 @@ version = "0.13.0-dev" dependencies = [ "anyhow", "arrayvec", - "bitflags 2.6.0", + "bitflags", "derive_more", "hex-literal", "indexmap", "ipnetwork", - "itertools 0.13.0", + "itertools", "mockall", "nix", "parking_lot", @@ -2530,7 +2676,7 @@ dependencies = [ "crossbeam", "dns-lookup", "hickory-resolver", - "itertools 0.13.0", + "itertools", "parking_lot", "thiserror 2.0.6", ] @@ -2541,7 +2687,7 @@ version = "0.13.0-dev" dependencies = [ "anyhow", "hex-literal", - "itertools 0.13.0", + "itertools", "thiserror 2.0.6", ] @@ -2572,18 +2718,19 @@ dependencies = [ "encoding_rs_io", "etcetera", "humantime", + "i18n-embed", + "i18n-embed-fl", "insta", - "itertools 0.13.0", + "itertools", "maxminddb", "petgraph", "pretty_assertions", "ratatui", - "rust-i18n", + "rust-embed", "serde", "serde_json", "serde_with", "strum", - "sys-locale", "test-case", "toml 0.8.19", "tracing", @@ -2616,6 +2763,40 @@ dependencies = [ "wintun-bindings", ] +[[package]] +name = "type-map" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f" +dependencies = [ + "rustc-hash", +] + +[[package]] +name = "typenum" +version = "1.17.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" + +[[package]] +name = "unic-langid" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23dd9d1e72a73b25e07123a80776aae3e7b0ec461ef94f9151eed6ec88005a44" +dependencies = [ + "unic-langid-impl", +] + +[[package]] +name = "unic-langid-impl" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0a5422c1f65949306c99240b81de9f3f15929f5a8bfe05bb44b034cc8bf593e5" +dependencies = [ + "serde", + "tinystr", +] + [[package]] name = "unicode-ident" version = "1.0.14" @@ -2634,7 +2815,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b3644627a5af5fa321c95b9b235a72fd24cd29c648c2c379431e6628655627bf" dependencies = [ - "itertools 0.13.0", + "itertools", "unicode-segmentation", "unicode-width 0.1.14", ] @@ -2686,6 +2867,12 @@ version = "0.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b7e5d4d90034032940e4ace0d9a9a057e7a45cd94e6c007832e39edb82f6d" +[[package]] +name = "version_check" +version = "0.9.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" + [[package]] name = "walkdir" version = "2.5.0" @@ -2950,15 +3137,6 @@ 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 = "winnow" version = "0.6.20" diff --git a/Cargo.toml b/Cargo.toml index 220350b6..db074ce1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -61,13 +61,14 @@ petgraph = "0.6.5" pretty_assertions = "1.4.1" rand = "0.8.5" ratatui = "0.29.0" -rust-i18n = "3.1.2" +rust-embed = "8.5" +i18n-embed = { version = "0.15", features = ["fluent-system", "desktop-requester"] } +i18n-embed-fl = "0.9" serde = { version = "1.0.201", default-features = false } serde_json = { version = "1.0.117", default-features = false } serde_with = { version = "3.11.0", default-features = false, features = ["macros"] } socket2 = "0.5.8" strum = { version = "0.26.3", default-features = false } -sys-locale = "0.3.2" test-case = "3.3.1" thiserror = "2.0.3" tokio = "1.41.1" diff --git a/Dockerfile b/Dockerfile index d636dd1d..fcd1910b 100644 --- a/Dockerfile +++ b/Dockerfile @@ -16,6 +16,8 @@ COPY crates/trippy-dns/Cargo.toml /app/crates/trippy-dns/Cargo.toml COPY crates/trippy-packet/Cargo.toml /app/crates/trippy-packet/Cargo.toml COPY crates/trippy-privilege/Cargo.toml /app/crates/trippy-privilege/Cargo.toml COPY examples/ /app/examples/ +COPY crates/trippy-tui/i18n/ /app/crates/trippy-tui/i18n/ +COPY crates/trippy-tui/i18n.toml /app/crates/trippy-tui/i18n.toml # dummy build to cache dependencies RUN echo "fn main() {}" > /app/crates/trippy/src/main.rs diff --git a/crates/trippy-tui/Cargo.toml b/crates/trippy-tui/Cargo.toml index 2134f2bd..b8471495 100644 --- a/crates/trippy-tui/Cargo.toml +++ b/crates/trippy-tui/Cargo.toml @@ -41,12 +41,13 @@ itertools.workspace = true maxminddb.workspace = true petgraph.workspace = true ratatui.workspace = true -rust-i18n.workspace = true +rust-embed.workspace = true +i18n-embed.workspace = true +i18n-embed-fl.workspace = true serde = { workspace = true, default-features = false, features = [ "derive" ] } serde_json.workspace = true serde_with.workspace = true strum = { workspace = true, default-features = false, features = [ "std", "derive" ] } -sys-locale.workspace = true toml = { workspace = true, default-features = false, features = [ "parse" ] } tracing-chrome.workspace = true tracing-subscriber = { workspace = true, default-features = false, features = [ "env-filter", "json" ] } @@ -59,4 +60,4 @@ pretty_assertions.workspace = true test-case.workspace = true [lints] -workspace = true \ No newline at end of file +workspace = true diff --git a/crates/trippy-tui/i18n.toml b/crates/trippy-tui/i18n.toml new file mode 100644 index 00000000..76f7c310 --- /dev/null +++ b/crates/trippy-tui/i18n.toml @@ -0,0 +1,4 @@ +fallback_language = "en" + +[fluent] +assets_dir = "i18n" diff --git a/crates/trippy-tui/i18n/de/trippy-tui.ftl b/crates/trippy-tui/i18n/de/trippy-tui.ftl new file mode 100644 index 00000000..8aac21ae --- /dev/null +++ b/crates/trippy-tui/i18n/de/trippy-tui.ftl @@ -0,0 +1,110 @@ +auto = auto +awaited = erwartet +awaiting_data = Warten auf Daten... +bsod_failed = Trippy ist fehlgeschlagen :( +bsod_quit = Drücken Sie q, um zu beenden +chart = chart +column_avg = Durchschnitt +column_best = Beste +column_bloss = Bloss +column_code = Code +column_dprt = Dprt +column_fail = Fehlgeschlagen +column_floss = Floss +column_floss_pct = Floss% +column_host = Host +column_javg = Javg +column_jint = Jint +column_jmax = Jmax +column_jttr = Jttr +column_last = Letzte +column_loss_pct = Verlust% +column_nat = Nat +column_recv = Recv +column_seq = Seq +column_snd = Snd +column_sprt = Sprt +column_stdev = StdAbw +column_sts = Sts +column_type = Typ +column_wrst = Schlechteste +details = detail +discovered = { $hop_count } gefundene hops +discovered_flows = { $hop_count } gefundene hops und { $flow_count } eindeutige { $plural_flows } +dns_failed = Fehlgeschlagen +dns_timeout = Zeitüberschreitung +ext = Ext +flow = fluss +flows = flüsse +geo = Geo +geoip_multiple_data_for_hop = Mehrere GeoIp-Standorte für den Hop +geoip_no_data_for_hop = Keine GeoIp-Daten für den Hop +geoip_not_enabled = GeoIp nicht aktiviert +header_help = hilfe +header_quit = beenden +header_settings = einstellungen +help_copyright = Copyright 2022 Trippy Mitwirkende +help_license = Verteilt unter der Apache-Lizenz 2.0 +help_show_bindings = Drücken Sie [{ $key }], um alle Tastenbelegungen anzuzeigen +help_show_columns = Drücken Sie [{ $key }], um alle Spalten anzuzeigen +help_show_settings = Drücken Sie [{ $key }], um alle Einstellungen anzuzeigen +help_tagline = Ein Netzwerkdiagnosetool +hidden = Versteckt +hop = Hop +host = Host +icmp = icmp +info = Info +kilometer = km +labels = etiketten +name = Name +na = n/a +no = Nein +none = keiner +no_response = Keine Antwort +not_enabled = nicht aktiviert +not_found = nicht gefunden +off = aus +on = an +pos = Pos +privacy = datenschutz +privileged = privilegiert +rtt = RTT +samples = Proben +settings_info = Info +settings_tab_bindings_desc = Tui-Tastenbelegungen +settings_tab_bindings_title = Tastenbelegungen +settings_tab_columns_desc = Tui-Tabellenspalten. Drücken Sie [{ $c }], um eine Spalte ein- oder auszuschalten, und verwenden Sie die Tasten [{ $d }] und [{ $u }], um die Spaltenreihenfolge zu ändern. +settings_tab_columns_title = Spalten +settings_tab_dns_desc = Einstellungen, die steuern, wie DNS-Lookups durchgeführt werden +settings_tab_dns_title = DNS +settings_tab_geoip_desc = Einstellungen im Zusammenhang mit GeoIp +settings_tab_geoip_title = GeoIp +settings_table_header_setting = Einstellung +settings_table_header_value = Wert +settings_tab_theme_desc = Tui-Themefarben +settings_tab_theme_title = Darstellung +settings_tab_trace_desc = Einstellungen, die die Tracing-Strategie steuern +settings_tab_trace_title = Trace +settings_tab_tui_desc = Einstellungen, die steuern, wie Daten in diesem Tui angezeigt werden +settings_tab_tui_title = Tui +status_failed = Fehlgeschlagen +status_failures = { $failure_count } von { $total_probes } ({ $failure_rate }%) sonden sind fehlgeschlagen +status_frozen = Eingefroren +status_running = Läuft +status = Status +target = Ziel +tcp = tcp +title_chart = Diagramm +title_flows = Flüsse +title_frequency = Frequenz +title_help = Hilfe +title_hops = Hops +title_map = Karte +title_samples = Proben +title_settings = Einstellungen +title_traces = Spuren +trippy = trippy +udp = udp +unknown = unbekannt +unprivileged = unprivilegiert +yes = Ja diff --git a/crates/trippy-tui/i18n/en/trippy-tui.ftl b/crates/trippy-tui/i18n/en/trippy-tui.ftl new file mode 100644 index 00000000..a5dd89b6 --- /dev/null +++ b/crates/trippy-tui/i18n/en/trippy-tui.ftl @@ -0,0 +1,110 @@ +auto = auto +awaited = awaited +awaiting_data = Awaiting data... +bsod_failed = Trippy Failed :( +bsod_quit = Press q to quit +chart = chart +column_avg = Avg +column_best = Best +column_bloss = Bloss +column_code = Code +column_dprt = Dprt +column_fail = Fail +column_floss = Floss +column_floss_pct = Floss% +column_host = Host +column_javg = Javg +column_jint = Jint +column_jmax = Jmax +column_jttr = Jttr +column_last = Last +column_loss_pct = Loss% +column_nat = Nat +column_recv = Recv +column_seq = Seq +column_snd = Snd +column_sprt = Sprt +column_stdev = StDev +column_sts = Sts +column_type = Type +column_wrst = Wrst +details = detail +discovered = discovered { $hop_count } hops +discovered_flows = discovered { $hop_count } hops and { $flow_count } unique { $plural_flows } +dns_failed = Failed +dns_timeout = Timeout +ext = Ext +flow = flow +flows = flows +geo = Geo +geoip_multiple_data_for_hop = Multiple GeoIp locations for hop +geoip_no_data_for_hop = No GeoIp data for hop +geoip_not_enabled = GeoIp not enabled +header_help = help +header_quit = quit +header_settings = settings +help_copyright = Copyright 2022 Trippy Contributors +help_license = Distributed under the Apache License 2.0 +help_show_bindings = Press [{ $key }] to show all bindings +help_show_columns = Press [{ $key }] to show all columns +help_show_settings = Press [{ $key }] to show all settings +help_tagline = A network diagnostic tool +hidden = Hidden +hop = Hop +host = Host +icmp = icmp +info = Info +kilometer = km +labels = labels +name = Name +na = n/a +none = none +no = No +no_response = No response +not_enabled = not enabled +not_found = not found +off = off +on = on +pos = Pos +privacy = privacy +privileged = privileged +rtt = RTT +samples = Samples +settings_info = Info +settings_tab_bindings_desc = Tui key bindings +settings_tab_bindings_title = Bindings +settings_tab_columns_desc = Tui table columns. Press [{ $c }] to toggle a column on or off and use the [{ $d }] and [{ $u }] keys to change the column order. +settings_tab_columns_title = Columns +settings_tab_dns_desc = Settings which control how DNS lookups are performed +settings_tab_dns_title = DNS +settings_tab_geoip_desc = Settings relating to GeoIp +settings_tab_geoip_title = GeoIp +settings_table_header_setting = Setting +settings_table_header_value = Value +settings_tab_theme_desc = Tui theme colors +settings_tab_theme_title = Theme +settings_tab_trace_desc = Settings which control the tracing strategy +settings_tab_trace_title = Trace +settings_tab_tui_desc = Settings which control how data is displayed in this Tui +settings_tab_tui_title = Tui +status_failed = Failed +status_failures = { $failure_count } of { $total_probes } ({ $failure_rate }%) probes failed +status_frozen = Frozen +status_running = Running +status = Status +target = Target +tcp = tcp +title_chart = Chart +title_flows = Flows +title_frequency = Frequency +title_help = Help +title_hops = Hops +title_map = Map +title_samples = Samples +title_settings = Settings +title_traces = Traces +trippy = trippy +udp = udp +unknown = unknown +unprivileged = unprivileged +yes = Yes diff --git a/crates/trippy-tui/i18n/es/trippy-tui.ftl b/crates/trippy-tui/i18n/es/trippy-tui.ftl new file mode 100644 index 00000000..74ff344a --- /dev/null +++ b/crates/trippy-tui/i18n/es/trippy-tui.ftl @@ -0,0 +1,110 @@ +auto = automático +awaited = esperado +awaiting_data = Esperando datos... +bsod_failed = Trippy tuvo un problema :( +bsod_quit = Presiona q para salir +chart = chart +column_avg = Prom +column_best = Mejor +column_bloss = Bloss +column_code = Código +column_dprt = Dprt +column_fail = Falló +column_floss = Floss +column_floss_pct = Floss% +column_host = Host +column_javg = PromJit +column_jint = JitInt +column_jmax = JitMax +column_jttr = Jttr +column_last = Último +column_loss_pct = % Perdidos +column_nat = Nat +column_recv = Recibidos +column_seq = Seq +column_snd = Enviados +column_sprt = Sprt +column_stdev = DesvE +column_sts = Est +column_type = Tipo +column_wrst = Peor +details = detalles +discovered_flows = se descubrieron { $hop_count } saltos y { $flow_count } únicos { $plural_flows } +discovered = se descubrieron { $hop_count } saltos +dns_failed = Fallido +dns_timeout = Tiempo de espera +ext = Ext +flow = flujo +flows = flujos +geo = Geo +geoip_multiple_data_for_hop = Múltiples ubicaciones de GeoIp para el salto +geoip_no_data_for_hop = No hay datos de GeoIp para el salto +geoip_not_enabled = GeoIp no habilitado +header_help = ayuda +header_quit = salir +header_settings = configuraciones +help_copyright = Derechos de autor 2022 Contribuidores de Trippy +help_license = Distribuido bajo la Licencia Apache 2.0 +help_show_bindings = Presiona [{ $key }] para mostrar todos los atajos +help_show_columns = Presiona [{ $key }] para mostrar todas las columnas +help_show_settings = Presiona [{ $key }] para mostrar todas las configuraciones +help_tagline = Una herramienta de diagnóstico de red +hidden = Oculto +hop = Salto +host = Host +icmp = icmp +info = Información +kilometer = km +labels = etiquetas +name = Nombre +na = n/d +none = ninguno +no = No +no_response = Sin respuesta +not_enabled = no habilitado +not_found = no encontrado +off = inactivo +on = activo +pos = Pos +privacy = privacidad +privileged = privilegiado +rtt = RTT +samples = Muestras +settings_info = Información +settings_tab_bindings_desc = Atajos de teclado Tui +settings_tab_bindings_title = Atajos +settings_tab_columns_desc = Columnas de la tabla Tui. Presiona [{ $c }] para activar o desactivar una columna y usa las teclas [{ $d }] y [{ $u }] para cambiar el orden de las columnas. +settings_tab_columns_title = Columnas +settings_tab_dns_desc = Configuraciones que controlan cómo se realizan las búsquedas de DNS +settings_tab_dns_title = DNS +settings_tab_geoip_desc = Configuraciones relacionadas con GeoIp +settings_tab_geoip_title = GeoIp +settings_table_header_setting = Configuración +settings_table_header_value = Valor +settings_tab_theme_desc = Colores del tema Tui +settings_tab_theme_title = Tema +settings_tab_trace_desc = Configuraciones que controlan la estrategia de rastreo +settings_tab_trace_title = Rastrear +settings_tab_tui_desc = Configuraciones que controlan cómo se muestran los datos en este Tui +settings_tab_tui_title = Tui +status = Estado +status_failed = Fallido +status_failures = { $failure_count } de { $total_probes } ({ $failure_rate }%) sondas fallaron +status_frozen = Congelado +status_running = En ejecución +target = Objetivo +tcp = tcp +title_chart = Gráfico +title_flows = Flujos +title_frequency = Frecuencia +title_help = Ayuda +title_hops = Saltos +title_map = Mapa +title_samples = Muestras +title_settings = Configuraciones +title_traces = Trazas +trippy = trippy +udp = udp +unknown = desconocido +unprivileged = no privilegiado +yes = Sí diff --git a/crates/trippy-tui/i18n/fr/trippy-tui.ftl b/crates/trippy-tui/i18n/fr/trippy-tui.ftl new file mode 100644 index 00000000..3f455c65 --- /dev/null +++ b/crates/trippy-tui/i18n/fr/trippy-tui.ftl @@ -0,0 +1,110 @@ +auto = automatique +awaited = attendu +awaiting_data = En attente de données... +bsod_failed = Trippy a échoué :( +bsod_quit = Appuyez sur q pour quitter +chart = chart +column_avg = Moyenne +column_best = Meilleur +column_bloss = Bloss +column_code = Code +column_dprt = Pdest +column_fail = Échec +column_floss = Floss +column_floss_pct = Floss% +column_host = Hôte +column_javg = GigMoy +column_jint = GigInt +column_jmax = GigMax +column_jttr = Gigue +column_last = Dernier +column_loss_pct = % Perdus +column_nat = Nat +column_recv = Reçus +column_seq = Seq +column_snd = Envoyés +column_sprt = Psrc +column_stdev = ÉcTyp +column_sts = État +column_type = Type +column_wrst = Pire +details = détail +discovered = { $hop_count } sauts découverts +discovered_flows = { $hop_count } sauts et { $flow_count } { $plural_flows } uniques découverts +dns_failed = Échec +dns_timeout = Délai dépassé +ext = Ext +flow = flux +flows = flux +geo = Géo +geoip_multiple_data_for_hop = Emplacements GeoIp multiples pour le saut +geoip_no_data_for_hop = Pas de données GeoIp pour le saut +geoip_not_enabled = GeoIp non activé +header_help = aide +header_quit = quitter +header_settings = paramètres +help_copyright = Copyright 2022 Contributeurs de Trippy +help_license = Distribué sous licence Apache 2.0 +help_show_bindings = Appuyez sur [{ $key }] pour afficher tous les raccourcis clavier +help_show_columns = Appuyez sur [{ $key }] pour afficher toutes les colonnes +help_show_settings = Appuyez sur [{ $key }] pour afficher tous les paramètres +help_tagline = Un outil de diagnostic réseau +hidden = Caché +hop = Saut +host = Hôte +icmp = icmp +info = Information +kilometer = km +labels = étiquettes +name = Nom +na = non disponible +none = aucun +no = Non +no_response = Pas de réponse +not_enabled = non activé +not_found = non trouvé +off = désactivé +on = activé +pos = Pos +privacy = confidentialité +privileged = privilégié +rtt = RTT +samples = Échantillons +settings_info = Information +settings_tab_bindings_desc = Raccourcis clavier Tui +settings_tab_bindings_title = Raccourcis clavier +settings_tab_columns_desc = Colonnes de table Tui. Appuyez sur [{ $c }] pour activer ou désactiver une colonne et utilisez les touches [{ $d }] et [{ $u }] pour changer l'ordre des colonnes. +settings_tab_columns_title = Colonnes +settings_tab_dns_desc = Paramètres qui contrôlent la façon dont les recherches DNS sont effectuées +settings_tab_dns_title = DNS +settings_tab_geoip_desc = Paramètres relatifs à GeoIp +settings_tab_geoip_title = GeoIp +settings_table_header_setting = Paramètres +settings_table_header_value = Valeur +settings_tab_theme_desc = Couleurs du thème Tui +settings_tab_theme_title = Thème +settings_tab_trace_desc = Paramètres qui contrôlent la stratégie de traçage +settings_tab_trace_title = Tracer +settings_tab_tui_desc = Paramètres qui contrôlent la façon dont les données sont affichées dans ce Tui +settings_tab_tui_title = Tui +status_failed = Échec +status_failures = { $failure_count } sur { $total_probes } ({ $failure_rate }%) sondes ont échoué +status_frozen = Gelé +status_running = En cours +status = Statut +target = Cible +tcp = tcp +title_chart = Graphique +title_flows = Flux +title_frequency = Fréquence +title_help = Aide +title_hops = Sauts +title_map = Carte +title_samples = Échantillons +title_settings = Paramètres +title_traces = Traces +trippy = trippy +udp = udp +unknown = inconnu +unprivileged = non privilégié +yes = Oui diff --git a/crates/trippy-tui/i18n/it/trippy-tui.ftl b/crates/trippy-tui/i18n/it/trippy-tui.ftl new file mode 100644 index 00000000..d20e39e2 --- /dev/null +++ b/crates/trippy-tui/i18n/it/trippy-tui.ftl @@ -0,0 +1,110 @@ +auto = auto +awaited = atteso +awaiting_data = In attesa di dati... +bsod_failed = Trippy ha avuto un problema :( +bsod_quit = Premi q per uscire +chart = chart +column_avg = Media +column_best = Migliore +column_bloss = Bloss +column_code = Codice +column_dprt = Dprt +column_fail = Falliti +column_floss = Floss +column_floss_pct = Floss% +column_host = Host +column_javg = Javg +column_jint = Jint +column_jmax = Jmax +column_jttr = Jttr +column_last = Ultimo +column_loss_pct = Persi% +column_nat = Nat +column_recv = Recv +column_seq = Seq +column_snd = Snd +column_sprt = Sprt +column_stdev = StDev +column_sts = Stato +column_type = Tipo +column_wrst = Peggiore +details = dettagli +discovered = { $hop_count } salti trovati +discovered_flows = scoperti { $hop_count } salti e { $flow_count } { $plural_flows } unici +dns_failed = Fallito +dns_timeout = Tempo scaduto +ext = Est +flow = flusso +flows = flussi +geo = Geo +geoip_multiple_data_for_hop = Posizioni GeoIp multiple per il salto +geoip_no_data_for_hop = Nessun dato GeoIp per il salto +geoip_not_enabled = GeoIp non abilitato +header_help = aiuto +header_quit = uscita +header_settings = impostazioni +help_copyright = Copyright 2022 - Collaboratori di Trippy +help_license = Distribuito con licenza Apache 2.0 +help_show_bindings = Premi [{ $key }] per visualizzare tutti i collegamenti +help_show_columns = Premi [{ $key }] per visualizzare tutte le colonne +help_show_settings = Premi [{ $key }] per visualizzare tutte le impostazioni +help_tagline = Uno strumento diagnostico di rete +hidden = Nascosto +hop = Salto +host = Host +icmp = icmp +info = Info +kilometer = km +labels = etichette +name = Nome +na = n/d +none = nessuno +no = No +no_response = Nessuna risposta +not_enabled = non abilitato +not_found = non trovato +off = off +on = on +pos = Pos +privacy = privacy +privileged = privilegiato +rtt = RTT +samples = Campioni +settings_info = Info +settings_tab_bindings_desc = Collegamenti chiave Tui +settings_tab_bindings_title = Collegamenti +settings_tab_columns_desc = Colonne della tabella Tui. Premi [{ $c }] per attivare o disattivare una colonna e usa i tasti [{ $d }] e [{ $u }] per cambiare l'ordine delle colonne. +settings_tab_columns_title = Colonne +settings_tab_dns_desc = Impostazioni che controllano come vengono eseguite le ricerche DNS +settings_tab_dns_title = DNS +settings_tab_geoip_desc = Impostazioni relative a GeoIp +settings_tab_geoip_title = GeoIp +settings_table_header_setting = Impostazione +settings_table_header_value = Valore +settings_tab_theme_desc = Colori del tema Tui +settings_tab_theme_title = Tema +settings_tab_trace_desc = Impostazioni che controllano la strategia di tracciamento +settings_tab_trace_title = Traccia +settings_tab_tui_desc = Impostazioni che controllano come i dati vengono visualizzati in questo Tui +settings_tab_tui_title = Tui +status_failed = Fallito +status_failures = { $failure_count } di { $total_probes } ({ $failure_rate }%) prove fallite +status_frozen = Congelato +status_running = In esecuzione +status = Stato +target = Target +tcp = tcp +title_chart = Grafico +title_flows = Flussi +title_frequency = Frequenza +title_help = Aiuto +title_hops = Salti +title_map = Mappa +title_samples = Campioni +title_settings = Impostazioni +title_traces = Tracce +trippy = trippy +udp = udp +unknown = sconosciuto +unprivileged = non privilegiato +yes = Sì diff --git a/crates/trippy-tui/i18n/pt/trippy-tui.ftl b/crates/trippy-tui/i18n/pt/trippy-tui.ftl new file mode 100644 index 00000000..d5d16c6f --- /dev/null +++ b/crates/trippy-tui/i18n/pt/trippy-tui.ftl @@ -0,0 +1,111 @@ + +auto = automático +awaited = aguardado +awaiting_data = Aguardando dados... +bsod_failed = Trippy falhou :( +bsod_quit = Pressione q para sair +chart = chart +column_avg = Média +column_best = Melhor +column_bloss = Bloss +column_code = Código +column_dprt = Dprt +column_fail = Falha +column_floss = Floss +column_floss_pct = Floss% +column_host = Host +column_javg = Javg +column_jint = Jint +column_jmax = Jmax +column_jttr = Jttr +column_last = Último +column_loss_pct = % Perdidos +column_nat = Nat +column_recv = Recebidos +column_seq = Seq +column_snd = Enviados +column_sprt = Sprt +column_stdev = DesvPad +column_sts = Est +column_type = Tipo +column_wrst = Pior +details = detalhe +discovered = descobriu { $hop_count } saltos +discovered_flows = descobriu { $hop_count } saltos e { $flow_count } { $plural_flows } únicos +dns_failed = Falhou +dns_timeout = Tempo esgotado +ext = Ext +flow = fluxo +flows = fluxos +geo = Geo +geoip_multiple_data_for_hop = Múltiplas localizações GeoIp para o salto +geoip_no_data_for_hop = Nenhum dado GeoIp para o salto +geoip_not_enabled = GeoIp não ativado +header_help = ajuda +header_quit = sair +header_settings = configurações +help_copyright = Direitos autorais 2022 Colaboradores do Trippy +help_license = Distribuído sob a licença Apache 2.0 +help_show_bindings = Pressione [{ $key }] para mostrar todos os atalhos +help_show_columns = Pressione [{ $key }] para mostrar todas as colunas +help_show_settings = Pressione [{ $key }] para mostrar todas as configurações +help_tagline = Uma ferramenta de diagnóstico de rede +hidden = Oculto +hop = Salto +host = Host +icmp = icmp +info = Informação +kilometer = km +labels = etiquetas +name = Nome +na = n/d +no = Não +none = nenhum +no_response = Sem resposta +not_enabled = não ativado +not_found = não encontrado +off = desligado +on = ligado +pos = Pos +privacy = privacidade +privileged = privilegiado +rtt = RTT +samples = Amostras +settings_info = Informação +settings_tab_bindings_desc = Atalhos de teclado Tui +settings_tab_bindings_title = Atalhos +settings_tab_columns_desc = Colunas da tabela Tui. Pressione [{ $c }] para ativar ou desativar uma coluna e use as teclas [{ $d }] e [{ $u }] para alterar a ordem das colunas. +settings_tab_columns_title = Colunas +settings_tab_dns_desc = Configurações que controlam como as pesquisas DNS são realizadas +settings_tab_dns_title = DNS +settings_tab_geoip_desc = Configurações relacionadas ao GeoIp +settings_tab_geoip_title = GeoIp +settings_table_header_setting = Configuração +settings_table_header_value = Valor +settings_tab_theme_desc = Cores do tema Tui +settings_tab_theme_title = Tema +settings_tab_trace_desc = Configurações que controlam a estratégia de rastreamento +settings_tab_trace_title = Rastrear +settings_tab_tui_desc = Configurações que controlam como os dados são exibidos neste Tui +settings_tab_tui_title = Tui +status = Estado +status_failed = Falhou +status_failures = { $failure_count } de { $total_probes } ({ $failure_rate }%) sondas falharam +status_frozen = Congelado +status_running = Executando +target = Alvo +tcp = tcp +title_chart = Gráfico +title_flows = Fluxos +title_frequency = Frequência +title_help = Ajuda +title_hops = Saltos +title_map = Mapa +title_samples = Amostras +title_settings = Configurações +title_traces = Rastreios +trippy = trippy +udp = udp +unknown = desconhecido +unprivileged = não privilegiado +yes = Sim diff --git a/crates/trippy-tui/i18n/ru/trippy-tui.ftl b/crates/trippy-tui/i18n/ru/trippy-tui.ftl new file mode 100644 index 00000000..ef8c2015 --- /dev/null +++ b/crates/trippy-tui/i18n/ru/trippy-tui.ftl @@ -0,0 +1,110 @@ +auto = авто +awaited = ожидаемый +awaiting_data = Ожидание данных... +bsod_failed = Trippy не удалось :( +bsod_quit = Нажмите q для выхода +chart = chart +column_avg = Сред +column_best = Луч +column_bloss = Bloss +column_code = Код +column_dprt = Назн +column_fail = Неуд +column_floss = Floss +column_floss_pct = Floss% +column_host = Хост +column_javg = СреднДжитр +column_jint = ИнтДжитр +column_jmax = МаксДжитр +column_jttr = Джитр +column_last = Посл +column_loss_pct = Потери% +column_nat = Nat +column_recv = Получ +column_seq = Посл +column_snd = Отпр +column_sprt = Исх +column_stdev = СКО +column_sts = Статус +column_type = Тип +column_wrst = Худ +details = детали +discovered_flows = обнаружено { $hop_count } прыжков и { $flow_count } уникальных { $plural_flows } +discovered = обнаружено { $hop_count } прыжков +dns_failed = Не удалось +dns_timeout = Тайм-аут +ext = Расширение +flows = потоки +flow = поток +geoip_multiple_data_for_hop = Несколько местоположений GeoIp для прыжка +geoip_no_data_for_hop = Нет данных GeoIp для прыжка +geoip_not_enabled = GeoIp не активирован +geo = Гео +header_help = помощь +header_quit = Выход +header_settings = настройки +help_copyright = Авторское право 2022 Участники Trippy +help_license = Распространяется под лицензией Apache 2.0 +help_show_bindings = Нажмите [{ $key }], чтобы показать все привязки +help_show_columns = Нажмите [{ $key }], чтобы показать все столбцы +help_show_settings = Нажмите [{ $key }], чтобы показать все настройки +help_tagline = Инструмент диагностики сети +hidden = Скрыто +hop = Прыжок +host = Хост +icmp = icmp +info = Информация +kilometer = км +labels = метки +name = Имя +na = н/д +none = нет +no_response = Нет ответа +not_enabled = не активирован +not_found = не найдено +no = Нет +off = выкл +on = вкл +pos = Поз +privacy = конфиденциальность +privileged = привилегированный +rtt = RTT +samples = Образцы +settings_info = Информация +settings_tab_bindings_desc = Привязки клавиш Tui +settings_tab_bindings_title = Привязки +settings_tab_columns_desc = Столбцы таблицы Tui. Нажмите [{ $c }], чтобы включить или отключить столбец, и используйте клавиши [{ $d }] и [{ $u }], чтобы изменить порядок столбцов. +settings_tab_columns_title = Столбцы +settings_tab_dns_desc = Настройки, которые контролируют, как выполняются DNS-запросы +settings_tab_dns_title = DNS +settings_tab_geoip_desc = Настройки, касающиеся GeoIp +settings_tab_geoip_title = GeoIp +settings_table_header_setting = Настройка +settings_table_header_value = Значение +settings_tab_theme_desc = Цвета темы Tui +settings_tab_theme_title = Тема +settings_tab_trace_desc = Настройки, которые контролируют стратегию трассировки +settings_tab_trace_title = След +settings_tab_tui_desc = Настройки, которые контролируют, как данные отображаются в этом Tui +settings_tab_tui_title = Tui +status_failed = Не удалось +status_failures = { $failure_count } из { $total_probes } ({ $failure_rate }%) зондов не удалось +status_frozen = Заморожен +status_running = Запущен +status = Статус +target = Цель +tcp = tcp +title_chart = Диаграмма +title_flows = Потоки +title_frequency = Частота +title_help = Помощь +title_hops = Прыжки +title_map = Карта +title_samples = Образцы +title_settings = Настройки +title_traces = Следы +trippy = trippy +udp = udp +unknown = неизвестно +unprivileged = непривилегированный +yes = Да diff --git a/crates/trippy-tui/i18n/sv/trippy-tui.ftl b/crates/trippy-tui/i18n/sv/trippy-tui.ftl new file mode 100644 index 00000000..f575dc85 --- /dev/null +++ b/crates/trippy-tui/i18n/sv/trippy-tui.ftl @@ -0,0 +1,110 @@ +auto = automatisk +awaited = väntade +awaiting_data = Väntar på data... +bsod_failed = Trippy misslyckades :( +bsod_quit = Tryck på q för att avsluta +chart = chart +column_avg = Genomsnitt +column_best = Bäst +column_bloss = Bloss +column_code = Kod +column_dprt = Dprt +column_fail = Misslyckades +column_floss = Floss +column_floss_pct = Floss% +column_host = Värd +column_javg = Javg +column_jint = Jint +column_jmax = Jmax +column_jttr = Jttr +column_last = Senast +column_loss_pct = Förlust% +column_nat = Nat +column_recv = Mottagna +column_seq = Seq +column_snd = Skickat +column_sprt = Sprt +column_stdev = StDev +column_sts = Sts +column_type = Typ +column_wrst = Sämst +details = detaljer +discovered_flows = { $hop_count } hopp och unika { $flow_count } { $plural_flows } upptäckta +discovered = upptäckte { $hop_count } hopp +dns_failed = Misslyckades +dns_timeout = Tidsgräns nådd +ext = Ext +flow = flöde +flows = flöden +geo = Geo +geoip_multiple_data_for_hop = Flera GeoIp-platser för hopp +geoip_no_data_for_hop = Inga GeoIp-data för hopp +geoip_not_enabled = GeoIp inte aktiverad +header_help = hjälp +header_quit = avsluta +header_settings = inställningar +help_copyright = Upphovsrätt 2022 Trippy-bidragsgivare +help_license = Distribueras under Apache License 2.0 +help_show_bindings = Tryck på [{ $key }] för att visa alla kortkommando +help_show_columns = Tryck på [{ $key }] för att visa alla kolumner +help_show_settings = Tryck på [{ $key }] för att visa alla inställningar +help_tagline = Ett nätverksdiagnostikverktyg +hidden = Dold +hop = Hopp +host = Värd +icmp = icmp +info = Information +kilometer = km +labels = etiketter +na = ej tillgänglig +name = Namn +none = ingen +no = Nej +no_response = Inget svar +not_enabled = ej aktiverad +not_found = hittades inte +off = av +on = på +pos = Pos +privacy = integritet +privileged = privilegierad +rtt = RTT +samples = Prover +settings_info = Information +settings_tab_bindings_desc = Tui-kortkommando +settings_tab_bindings_title = Kortkommando +settings_tab_columns_desc = Tui-tabellkolumner. Tryck på [{ $c }] för att slå på eller av en kolumn och använd [{ $d }] och [{ $u }] för att ändra kolumnordningen. +settings_tab_columns_title = Kolumner +settings_tab_dns_desc = Inställningar som styr hur DNS-uppslag utförs +settings_tab_dns_title = DNS +settings_tab_geoip_desc = Inställningar som rör GeoIp +settings_tab_geoip_title = GeoIp +settings_table_header_setting = Inställning +settings_table_header_value = Värde +settings_tab_theme_desc = Tui-temafärger +settings_tab_theme_title = Tema +settings_tab_trace_desc = Inställningar som styr spårningsstrategin +settings_tab_trace_title = Spåra +settings_tab_tui_desc = Inställningar som styr hur data visas i detta Tui +settings_tab_tui_title = Tui +status_failed = Misslyckades +status_failures = { $failure_count } av { $total_probes } ({ $failure_rate }%) misslyckade prober +status_frozen = Frusen +status_running = Kör +status = Status +target = Mål +tcp = tcp +title_chart = Diagram +title_flows = Flöden +title_frequency = Frekvens +title_help = Hjälp +title_hops = Hopp +title_map = Karta +title_samples = Prover +title_settings = Inställningar +title_traces = Spår +trippy = trippy +udp = udp +unknown = okänd +unprivileged = oprivilegierad +yes = Ja diff --git a/crates/trippy-tui/i18n/tr/trippy-tui.ftl b/crates/trippy-tui/i18n/tr/trippy-tui.ftl new file mode 100644 index 00000000..39c23f1e --- /dev/null +++ b/crates/trippy-tui/i18n/tr/trippy-tui.ftl @@ -0,0 +1,110 @@ +auto = otomatik +awaited = beklenen +awaiting_data = Veri bekleniyor... +bsod_failed = Trippy Başarısız :( +bsod_quit = Çıkmak için q tuşuna basın +chart = chart +column_avg = Ort +column_best = En iyi +column_bloss = Bloss +column_code = Code +column_dprt = Dprt +column_fail = Başarısız +column_floss = Floss +column_floss_pct = Floss% +column_host = Ana bilgisayar +column_javg = Javg +column_jint = Jint +column_jmax = Jmax +column_jttr = Jttr +column_last = Son +column_loss_pct = Kayıp% +column_nat = Nat +column_recv = Alınan +column_seq = Seq +column_snd = Gönderilen +column_sprt = Sprt +column_stdev = StDev +column_sts = Sts +column_type = Type +column_wrst = En kötü +details = ayrıntılar +discovered = { $hop_count } atlanan keşfedildi +discovered_flows = { $hop_count } atlanan ve { $flow_count } benzersiz { $plural_flows } keşfedildi +dns_failed = Başarısız +dns_timeout = Zaman aşımı +ext = Uzantı +flow = akış +flows = akışlar +geo = Coğrafi +geoip_multiple_data_for_hop = Hop için birden fazla GeoIp konumu +geoip_no_data_for_hop = Hop için GeoIp verisi yok +geoip_not_enabled = GeoIp etkin değil +header_help = yardım +header_quit = cıkış +header_settings = ayarlar +help_copyright = Telif Hakkı 2022 - Trippy'ye Katkıda Bulunanlar +help_license = Apache Lisansı 2.0 altında dağıtılmıştır +help_show_bindings = Tüm bağlantıları görmek için [{ $key }] tuşuna basın +help_show_columns = Tüm sütunları görmek için [{ $key }] tuşuna basın +help_show_settings = Tüm ayarları görmek için [{ $key }] tuşuna basın +help_tagline = Bir ağ analiz aracı +hidden = Gizli +hop = Atla +host = Ana bilgisayar +icmp = icmp +info = Bilgi +kilometer = km +labels = etiketler +name = Ad +na = yok +no = Hayır +none = hiçbiri +no_response = Yanıt yok +not_enabled = etkin değil +not_found = bulunamadı +off = kapalı +on = açık +pos = Poz +privacy = gizlilik +privileged = ayrıcalıklı +rtt = RTT +samples = Örnekler +settings_info = Bilgi +settings_tab_bindings_desc = Tui tuş ayarları +settings_tab_bindings_title = Bağlantılar +settings_tab_columns_desc = Tui tablo sütunları. Bir sütunu açmak veya kapatmak için [{ $c }] tuşuna basın ve sütun sırasını değiştirmek için [{ $d }] ve [{ $u }] tuşlarını kullanın. +settings_tab_columns_title = Sütunlar +settings_tab_dns_desc = DNS aramalarının nasıl yapıldığını kontrol eden ayarlar +settings_tab_dns_title = DNS +settings_tab_geoip_desc = GeoIp ile ilgili ayarlar +settings_tab_geoip_title = GeoIp +settings_table_header_setting = Ayar +settings_table_header_value = Değer +settings_tab_theme_desc = Tui tema renkleri +settings_tab_theme_title = Tema +settings_tab_trace_desc = İzleme stratejisini kontrol eden ayarlar +settings_tab_trace_title = İz +settings_tab_tui_desc = Arayüzde verilerin nasıl görüntülendiğini kontrol eden ayarlar +settings_tab_tui_title = Tui +status = Durum +status_failed = Başarısız +status_failures = { $failure_count } / { $total_probes } ({ $failure_rate }%) sondajın başarısız olması +status_frozen = Dondurulmuş +status_running = Çalışıyor +target = Hedef +tcp = tcp +title_chart = Grafik +title_flows = Akışlar +title_frequency = Sıklık +title_help = Yardım +title_hops = Atlananlar +title_map = Harita +title_samples = Örnekler +title_settings = Ayarlar +title_traces = İzler +trippy = trippy +udp = udp +unknown = bilinmeyen +unprivileged = ayrıcalıksız +yes = Evet diff --git a/crates/trippy-tui/i18n/zh/trippy-tui.ftl b/crates/trippy-tui/i18n/zh/trippy-tui.ftl new file mode 100644 index 00000000..fd5aa92d --- /dev/null +++ b/crates/trippy-tui/i18n/zh/trippy-tui.ftl @@ -0,0 +1,110 @@ +auto = 自动 +awaited = 等待 +awaiting_data = 等待数据…… +bsod_failed = Trippy 失败 :( +bsod_quit = 按 q 退出 +chart = chart +column_avg = 平均 +column_best = 最佳 +column_bloss = Bloss +column_code = 代码 +column_dprt = 目标 +column_fail = 失败 +column_floss = Floss +column_floss_pct = Floss% +column_host = 主机 +column_javg = 均抖 +column_jint = 抖动间隔 +column_jmax = 最大抖 +column_jttr = 抖动 +column_last = 最后 +column_loss_pct = 丢包率 +column_nat = 网络地址转换 +column_recv = 接收 +column_seq = 序列 +column_snd = 发出 +column_sprt = 源端 +column_stdev = 标准差 +column_sts = 状态 +column_type = 类型 +column_wrst = 最差 +details = 详情 +discovered_flows = 发现 { $hop_count } 跳,{ $flow_count } 个唯一{ $plural_flow } +discovered = 发现 { $hop_count } 跳 +dns_failed = 失败 +dns_timeout = 超时 +ext = 扩展 +flows = 流量 +flow = 流量 +geoip_multiple_data_for_hop = 多个 GeoIp 位置 +geoip_no_data_for_hop = 无 GeoIp 数据 +geoip_not_enabled = GeoIp 未启用 +geo = 地理坐标 +header_help = 帮助 +header_quit = 退出 +header_settings = 设置 +help_copyright = 版权所有 2022 Trippy 贡献者 +help_license = 以 Apache-2.0 许可分发 +help_show_bindings = 按 [{ $key }] 显示所有绑定 +help_show_columns = 按 [{ $key }] 显示所有列 +help_show_settings = 按 [{ $key }] 显示所有设置 +help_tagline = 网络诊断工具 +hidden = 隐藏 +hop = 跳 +host = 主机 +icmp = icmp +info = 信息 +kilometer = 公里 +labels = 标签 +name = 名称 +na = 无 +none = 无 +no_response = 无响应 +not_enabled = 未启用 +not_found = 未找到 +no = 否 +off = 关 +on = 开 +pos = 位置 +privacy = 隐私 +privileged = 特权 +rtt = 往返时间 +samples = 样本 +settings_info = 信息 +settings_tab_bindings_desc = 按键绑定设置 +settings_tab_bindings_title = 绑定 +settings_tab_columns_desc = 终端用户界面表格列。按 [{ $c }] 切换列的显示和隐藏,使用 [{ $d }] 和 [{ $u }] 键更改列的顺序。 +settings_tab_columns_title = 列 +settings_tab_dns_desc = DNS 查询设置 +settings_tab_dns_title = DNS +settings_tab_geoip_desc = GeoIp 设置 +settings_tab_geoip_title = GeoIp +settings_table_header_setting = 设置 +settings_table_header_value = 值 +settings_tab_theme_desc = 主题颜色设置 +settings_tab_theme_title = 主题 +settings_tab_trace_desc = 跟踪策略设置 +settings_tab_trace_title = 跟踪 +settings_tab_tui_desc = 数据显示方式设置 +settings_tab_tui_title = 终端用户界面 +status_failed = 失败 +status_failures = { $failure_count } 个失败,共探测到 { $total_probes } 个({ $failure_rate }%) +status_frozen = 冻结 +status_running = 运行中 +status = 状态 +target = 目标 +tcp = tcp +title_chart = 图表 +title_flows = 流量 +title_frequency = 频率 +title_help = 帮助 +title_hops = 跳 +title_map = 地图 +title_samples = 样本 +title_settings = 设置 +title_traces = 跟踪 +trippy = trippy +udp = udp +unknown = 未知 +unprivileged = 非特权 +yes = 是 diff --git a/crates/trippy-tui/locales/app.toml b/crates/trippy-tui/locales/app.toml deleted file mode 100644 index c68b0c45..00000000 --- a/crates/trippy-tui/locales/app.toml +++ /dev/null @@ -1,1308 +0,0 @@ -_version = 2 - -[trippy] -en = "trippy" -fr = "trippy" -tr = "trippy" -it = "trippy" -pt = "trippy" -zh = "trippy" -sv = "trippy" -ru = "trippy" -es = "trippy" -de = "trippy" - -[auto] -en = "auto" -fr = "automatique" -tr = "otomatik" -it = "auto" -pt = "automático" -zh = "自动" -sv = "automatisk" -ru = "авто" -es = "automático" -de = "auto" - -[on] -en = "on" -fr = "activé" -tr = "açık" -it = "on" -pt = "ligado" -zh = "开" -sv = "på" -ru = "вкл" -es = "activo" -de = "an" - -[off] -en = "off" -fr = "désactivé" -tr = "kapalı" -it = "off" -pt = "desligado" -zh = "关" -sv = "av" -ru = "выкл" -es = "inactivo" -de = "aus" - -[yes] -en = "Yes" -fr = "Oui" -tr = "Evet" -it = "Sì" -pt = "Sim" -zh = "是" -sv = "Ja" -ru = "Да" -es = "Sí" -de = "Ja" - -[no] -en = "No" -fr = "Non" -tr = "Hayır" -it = "No" -pt = "Não" -zh = "否" -sv = "Nej" -ru = "Нет" -es = "No" -de = "Nein" - -[none] -en = "none" -fr = "aucun" -tr = "hiçbiri" -it = "nessuno" -pt = "nenhum" -zh = "无" -sv = "ingen" -ru = "нет" -es = "ninguno" -de = "keiner" - -[hidden] -en = "Hidden" -fr = "Caché" -tr = "Gizli" -it = "Nascosto" -pt = "Oculto" -zh = "隐藏" -sv = "Dold" -ru = "Скрыто" -es = "Oculto" -de = "Versteckt" - -[flow] -en = "flow" -fr = "flux" -tr = "akış" -it = "flusso" -pt = "fluxo" -zh = "流量" -sv = "flöde" -ru = "поток" -es = "flujo" -de = "fluss" - -[flows] -en = "flows" -fr = "flux" -tr = "akışlar" -it = "flussi" -pt = "fluxos" -zh = "流量" -sv = "flöden" -ru = "потоки" -es = "flujos" -de = "flüsse" - -[target] -en = "Target" -fr = "Cible" -tr = "Hedef" -it = "Target" -pt = "Alvo" -zh = "目标" -sv = "Mål" -ru = "Цель" -es = "Objetivo" -de = "Ziel" - -[status] -en = "Status" -fr = "Statut" -tr = "Durum" -it = "Stato" -pt = "Estado" -zh = "状态" -sv = "Status" -ru = "Статус" -es = "Estado" -de = "Status" - -[details] -en = "detail" -fr = "détail" -tr = "ayrıntılar" -it = "dettagli" -pt = "detalhe" -zh = "详情" -sv = "detaljer" -ru = "детали" -es = "detalles" -de = "detail" - -[privileged] -en = "privileged" -fr = "privilégié" -tr = "ayrıcalıklı" -it = "privilegiato" -pt = "privilegiado" -zh = "特权" -sv = "privilegierad" -ru = "привилегированный" -es = "privilegiado" -de = "privilegiert" - -[unprivileged] -en = "unprivileged" -fr = "non privilégié" -tr = "ayrıcalıksız" -it = "non privilegiato" -pt = "não privilegiado" -zh = "非特权" -sv = "oprivilegierad" -ru = "непривилегированный" -es = "no privilegiado" -de = "unprivilegiert" - -[privacy] -en = "privacy" -fr = "confidentialité" -tr = "gizlilik" -it = "privacy" -pt = "privacidade" -zh = "隐私" -sv = "integritet" -ru = "конфиденциальность" -es = "privacidad" -de = "datenschutz" - -[na] -en = "n/a" -fr = "non disponible" -tr = "yok" -it = "n/d" -pt = "n/d" -zh = "无" -sv = "ej tillgänglig" -ru = "н/д" -es = "n/d" -de = "n/a" - -[discovered] -en = "discovered %{hop_count} hops" -fr = "%{hop_count} sauts découverts" -tr = "%{hop_count} atlanan keşfedildi" -it = "%{hop_count} salti trovati" -pt = "descobriu %{hop_count} saltos" -zh = "发现 %{hop_count} 跳" -sv = "upptäckte %{hop_count} hopp" -ru = "обнаружено %{hop_count} прыжков" -es = "se descubrieron %{hop_count} saltos" -de = "%{hop_count} gefundene hops" - -[discovered_flows] -en = "discovered %{hop_count} hops and %{flow_count} unique %{plural_flows}" -fr = "%{hop_count} sauts et %{flow_count} %{plural_flows} uniques découverts" -tr = "%{hop_count} atlanan ve %{flow_count} benzersiz %{plural_flows} keşfedildi" -it = "scoperti %{hop_count} salti e %{flow_count} %{plural_flows} unici" -pt = "descobriu %{hop_count} saltos e %{flow_count} %{plural_flows} únicos" -zh = "发现 %{hop_count} 跳,%{flow_count} 个唯一%{plural_flow}" -sv = "%{hop_count} hopp och unika %{flow_count} %{plural_flows} upptäckta" -ru = "обнаружено %{hop_count} прыжков и %{flow_count} уникальных %{plural_flows}" -es = "se descubrieron %{hop_count} saltos y %{flow_count} únicos %{plural_flows}" -de = "%{hop_count} gefundene hops und %{flow_count} eindeutige %{plural_flows}" - -[unknown] -en = "unknown" -fr = "inconnu" -tr = "bilinmeyen" -it = "sconosciuto" -pt = "desconhecido" -zh = "未知" -sv = "okänd" -ru = "неизвестно" -es = "desconocido" -de = "unbekannt" - -[icmp] -en = "icmp" -fr = "icmp" -tr = "icmp" -it = "icmp" -pt = "icmp" -zh = "icmp" -sv = "icmp" -ru = "icmp" -es = "icmp" -de = "icmp" - -[udp] -en = "udp" -fr = "udp" -tr = "udp" -it = "udp" -pt = "udp" -zh = "udp" -sv = "udp" -ru = "udp" -es = "udp" -de = "udp" - -[tcp] -en = "tcp" -fr = "tcp" -tr = "tcp" -it = "tcp" -pt = "tcp" -zh = "tcp" -sv = "tcp" -ru = "tcp" -es = "tcp" -de = "tcp" - -[status_failures] -en = "%{failure_count} of %{total_probes} (%{failure_rate}%) probes failed" -fr = "%{failure_count} sur %{total_probes} (%{failure_rate}%) sondes ont échoué" -tr = "%{failure_count} / %{total_probes} (%{failure_rate}%) sondajın başarısız olması" -it = "%{failure_count} di %{total_probes} (%{failure_rate}%) prove fallite" -pt = "%{failure_count} de %{total_probes} (%{failure_rate}%) sondas falharam" -zh = "%{failure_count} 个失败,共探测到 %{total_probes} 个(%{failure_rate}%)" -sv = "%{failure_count} av %{total_probes} (%{failure_rate}%) misslyckade prober" -ru = "%{failure_count} из %{total_probes} (%{failure_rate}%) зондов не удалось" -es = "%{failure_count} de %{total_probes} (%{failure_rate}%) sondas fallaron" -de = "%{failure_count} von %{total_probes} (%{failure_rate}%) sonden sind fehlgeschlagen" - -[status_failed] -en = "Failed" -fr = "Échec" -tr = "Başarısız" -it = "Fallito" -pt = "Falhou" -zh = "失败" -sv = "Misslyckades" -ru = "Не удалось" -es = "Fallido" -de = "Fehlgeschlagen" - -[status_running] -en = "Running" -fr = "En cours" -tr = "Çalışıyor" -it = "In esecuzione" -pt = "Executando" -zh = "运行中" -sv = "Kör" -ru = "Запущен" -es = "En ejecución" -de = "Läuft" - -[status_frozen] -en = "Frozen" -fr = "Gelé" -tr = "Dondurulmuş" -it = "Congelato" -pt = "Congelado" -zh = "冻结" -sv = "Frusen" -ru = "Заморожен" -es = "Congelado" -de = "Eingefroren" - -[awaiting_data] -en = "Awaiting data..." -fr = "En attente de données..." -tr = "Veri bekleniyor..." -it = "In attesa di dati..." -pt = "Aguardando dados..." -zh = "等待数据……" -sv = "Väntar på data..." -ru = "Ожидание данных..." -es = "Esperando datos..." -de = "Warten auf Daten..." - -[header_help] -en = "help" -fr = "aide" -tr = "yardım" -it = "aiuto" -pt = "ajuda" -zh = "帮助" -sv = "hjälp" -ru = "помощь" -es = "ayuda" -de = "hilfe" - -[header_settings] -en = "settings" -fr = "paramètres" -tr = "ayarlar" -it = "impostazioni" -pt = "configurações" -zh = "设置" -sv = "inställningar" -ru = "настройки" -es = "configuraciones" -de = "einstellungen" - -[header_quit] -en = "quit" -fr = "quitter" -tr = "cıkış" -it = "uscita" -pt = "sair" -zh = "退出" -sv = "avsluta" -ru = "Выход" -es = "salir" -de = "beenden" - -[title_hops] -en = "Hops" -fr = "Sauts" -tr = "Atlananlar" -it = "Salti" -pt = "Saltos" -zh = "跳" -sv = "Hopp" -ru = "Прыжки" -es = "Saltos" -de = "Hops" - -[title_frequency] -en = "Frequency" -fr = "Fréquence" -tr = "Sıklık" -it = "Frequenza" -pt = "Frequência" -zh = "频率" -sv = "Frekvens" -ru = "Частота" -es = "Frecuencia" -de = "Frequenz" - -[title_samples] -en = "Samples" -fr = "Échantillons" -tr = "Örnekler" -it = "Campioni" -pt = "Amostras" -zh = "样本" -sv = "Prover" -ru = "Образцы" -es = "Muestras" -de = "Proben" - -[title_traces] -en = "Traces" -fr = "Traces" -tr = "İzler" -it = "Tracce" -pt = "Rastreios" -zh = "跟踪" -sv = "Spår" -ru = "Следы" -es = "Trazas" -de = "Spuren" - -[title_flows] -en = "Flows" -fr = "Flux" -tr = "Akışlar" -it = "Flussi" -pt = "Fluxos" -zh = "流量" -sv = "Flöden" -ru = "Потоки" -es = "Flujos" -de = "Flüsse" - -[title_map] -en = "Map" -fr = "Carte" -tr = "Harita" -it = "Mappa" -pt = "Mapa" -zh = "地图" -sv = "Karta" -ru = "Карта" -es = "Mapa" -de = "Karte" - -[title_help] -en = "Help" -fr = "Aide" -tr = "Yardım" -it = "Aiuto" -pt = "Ajuda" -zh = "帮助" -sv = "Hjälp" -ru = "Помощь" -es = "Ayuda" -de = "Hilfe" - -[title_settings] -en = "Settings" -fr = "Paramètres" -tr = "Ayarlar" -it = "Impostazioni" -pt = "Configurações" -zh = "设置" -sv = "Inställningar" -ru = "Настройки" -es = "Configuraciones" -de = "Einstellungen" - -[bsod_failed] -en = "Trippy Failed :(" -fr = "Trippy a échoué :(" -tr = "Trippy Başarısız :(" -it = "Trippy ha avuto un problema :(" -pt = "Trippy falhou :(" -zh = "Trippy 失败 :(" -sv = "Trippy misslyckades :(" -ru = "Trippy не удалось :(" -es = "Trippy tuvo un problema :(" -de = "Trippy ist fehlgeschlagen :(" - -[bsod_quit] -en = "Press q to quit" -fr = "Appuyez sur q pour quitter" -tr = "Çıkmak için q tuşuna basın" -it = "Premi q per uscire" -pt = "Pressione q para sair" -zh = "按 q 退出" -sv = "Tryck på q för att avsluta" -ru = "Нажмите q для выхода" -es = "Presiona q para salir" -de = "Drücken Sie q, um zu beenden" - -[hop] -en = "Hop" -fr = "Saut" -tr = "Atla" -it = "Salto" -pt = "Salto" -zh = "跳" -sv = "Hopp" -ru = "Прыжок" -es = "Salto" -de = "Hop" - -[rtt] -en = "RTT" -fr = "RTT" -tr = "RTT" -it = "RTT" -pt = "RTT" -zh = "往返时间" -sv = "RTT" -ru = "RTT" -es = "RTT" -de = "RTT" - -[title_chart] -en = "Chart" -fr = "Graphique" -tr = "Grafik" -it = "Grafico" -pt = "Gráfico" -zh = "图表" -sv = "Diagram" -ru = "Диаграмма" -es = "Gráfico" -de = "Diagramm" - -[samples] -en = "Samples" -fr = "Échantillons" -tr = "Örnekler" -it = "Campioni" -pt = "Amostras" -zh = "样本" -sv = "Prover" -ru = "Образцы" -es = "Muestras" -de = "Proben" - -[host] -en = "Host" -fr = "Hôte" -tr = "Ana bilgisayar" -it = "Host" -pt = "Host" -zh = "主机" -sv = "Värd" -ru = "Хост" -es = "Host" -de = "Host" - -[no_response] -en = "No response" -fr = "Pas de réponse" -tr = "Yanıt yok" -it = "Nessuna risposta" -pt = "Sem resposta" -zh = "无响应" -sv = "Inget svar" -ru = "Нет ответа" -es = "Sin respuesta" -de = "Keine Antwort" - -[dns_failed] -en = "Failed" -fr = "Échec" -tr = "Başarısız" -it = "Fallito" -pt = "Falhou" -zh = "失败" -sv = "Misslyckades" -ru = "Не удалось" -es = "Fallido" -de = "Fehlgeschlagen" - -[dns_timeout] -en = "Timeout" -fr = "Délai dépassé" -tr = "Zaman aşımı" -it = "Tempo scaduto" -pt = "Tempo esgotado" -zh = "超时" -sv = "Tidsgräns nådd" -ru = "Тайм-аут" -es = "Tiempo de espera" -de = "Zeitüberschreitung" - -[labels] -en = "labels" -fr = "étiquettes" -tr = "etiketler" -it = "etichette" -pt = "etiquetas" -zh = "标签" -sv = "etiketter" -ru = "метки" -es = "etiquetas" -de = "etiketten" - -[not_enabled] -en = "not enabled" -fr = "non activé" -tr = "etkin değil" -it = "non abilitato" -pt = "não ativado" -zh = "未启用" -sv = "ej aktiverad" -ru = "не активирован" -es = "no habilitado" -de = "nicht aktiviert" - -[not_found] -en = "not found" -fr = "non trouvé" -tr = "bulunamadı" -it = "non trovato" -pt = "não encontrado" -zh = "未找到" -sv = "hittades inte" -ru = "не найдено" -es = "no encontrado" -de = "nicht gefunden" - -[awaited] -en = "awaited" -fr = "attendu" -tr = "beklenen" -it = "atteso" -pt = "aguardado" -zh = "等待" -sv = "väntade" -ru = "ожидаемый" -es = "esperado" -de = "erwartet" - -[name] -en = "Name" -fr = "Nom" -tr = "Ad" -it = "Nome" -pt = "Nome" -zh = "名称" -sv = "Namn" -ru = "Имя" -es = "Nombre" -de = "Name" - -[info] -en = "Info" -fr = "Information" -tr = "Bilgi" -it = "Info" -pt = "Informação" -zh = "信息" -sv = "Information" -ru = "Информация" -es = "Información" -de = "Info" - -[geo] -en = "Geo" -fr = "Géo" -tr = "Coğrafi" -it = "Geo" -pt = "Geo" -zh = "地理坐标" -sv = "Geo" -ru = "Гео" -es = "Geo" -de = "Geo" - -[pos] -en = "Pos" -fr = "Pos" -tr = "Poz" -it = "Pos" -pt = "Pos" -zh = "位置" -sv = "Pos" -ru = "Поз" -es = "Pos" -de = "Pos" - -[ext] -en = "Ext" -fr = "Ext" -tr = "Uzantı" -it = "Est" -pt = "Ext" -zh = "扩展" -sv = "Ext" -ru = "Расширение" -es = "Ext" -de = "Ext" - -[help_tagline] -en = "A network diagnostic tool" -fr = "Un outil de diagnostic réseau" -tr = "Bir ağ analiz aracı" -it = "Uno strumento diagnostico di rete" -pt = "Uma ferramenta de diagnóstico de rede" -zh = "网络诊断工具" -sv = "Ett nätverksdiagnostikverktyg" -ru = "Инструмент диагностики сети" -es = "Una herramienta de diagnóstico de red" -de = "Ein Netzwerkdiagnosetool" - -[help_show_settings] -en = "Press [%{key}] to show all settings" -fr = "Appuyez sur [%{key}] pour afficher tous les paramètres" -tr = "Tüm ayarları görmek için [%{key}] tuşuna basın" -it = "Premi [%{key}] per visualizzare tutte le impostazioni" -pt = "Pressione [%{key}] para mostrar todas as configurações" -zh = "按 [%{key}] 显示所有设置" -sv = "Tryck på [%{key}] för att visa alla inställningar" -ru = "Нажмите [%{key}], чтобы показать все настройки" -es = "Presiona [%{key}] para mostrar todas las configuraciones" -de = "Drücken Sie [%{key}], um alle Einstellungen anzuzeigen" - -[help_show_bindings] -en = "Press [%{key}] to show all bindings" -fr = "Appuyez sur [%{key}] pour afficher tous les raccourcis clavier" -tr = "Tüm bağlantıları görmek için [%{key}] tuşuna basın" -it = "Premi [%{key}] per visualizzare tutti i collegamenti" -pt = "Pressione [%{key}] para mostrar todos os atalhos" -zh = "按 [%{key}] 显示所有绑定" -sv = "Tryck på [%{key}] för att visa alla kortkommando" -ru = "Нажмите [%{key}], чтобы показать все привязки" -es = "Presiona [%{key}] para mostrar todos los atajos" -de = "Drücken Sie [%{key}], um alle Tastenbelegungen anzuzeigen" - -[help_show_columns] -en = "Press [%{key}] to show all columns" -fr = "Appuyez sur [%{key}] pour afficher toutes les colonnes" -tr = "Tüm sütunları görmek için [%{key}] tuşuna basın" -it = "Premi [%{key}] per visualizzare tutte le colonne" -pt = "Pressione [%{key}] para mostrar todas as colunas" -zh = "按 [%{key}] 显示所有列" -sv = "Tryck på [%{key}] för att visa alla kolumner" -ru = "Нажмите [%{key}], чтобы показать все столбцы" -es = "Presiona [%{key}] para mostrar todas las columnas" -de = "Drücken Sie [%{key}], um alle Spalten anzuzeigen" - -[help_license] -en = "Distributed under the Apache License 2.0" -fr = "Distribué sous licence Apache 2.0" -tr = "Apache Lisansı 2.0 altında dağıtılmıştır" -it = "Distribuito con licenza Apache 2.0" -pt = "Distribuído sob a licença Apache 2.0" -zh = "以 Apache-2.0 许可分发" -sv = "Distribueras under Apache License 2.0" -ru = "Распространяется под лицензией Apache 2.0" -es = "Distribuido bajo la Licencia Apache 2.0" -de = "Verteilt unter der Apache-Lizenz 2.0" - -[help_copyright] -en = "Copyright 2022 Trippy Contributors" -fr = "Copyright 2022 Contributeurs de Trippy" -tr = "Telif Hakkı 2022 - Trippy'ye Katkıda Bulunanlar" -it = "Copyright 2022 - Collaboratori di Trippy" -pt = "Direitos autorais 2022 Colaboradores do Trippy" -zh = "版权所有 2022 Trippy 贡献者" -sv = "Upphovsrätt 2022 Trippy-bidragsgivare" -ru = "Авторское право 2022 Участники Trippy" -es = "Derechos de autor 2022 Contribuidores de Trippy" -de = "Copyright 2022 Trippy Mitwirkende" - -[geoip_not_enabled] -en = "GeoIp not enabled" -fr = "GeoIp non activé" -tr = "GeoIp etkin değil" -it = "GeoIp non abilitato" -pt = "GeoIp não ativado" -zh = "GeoIp 未启用" -sv = "GeoIp inte aktiverad" -ru = "GeoIp не активирован" -es = "GeoIp no habilitado" -de = "GeoIp nicht aktiviert" - -[geoip_no_data_for_hop] -en = "No GeoIp data for hop" -fr = "Pas de données GeoIp pour le saut" -tr = "Hop için GeoIp verisi yok" -it = "Nessun dato GeoIp per il salto" -pt = "Nenhum dado GeoIp para o salto" -zh = "无 GeoIp 数据" -sv = "Inga GeoIp-data för hopp" -ru = "Нет данных GeoIp для прыжка" -es = "No hay datos de GeoIp para el salto" -de = "Keine GeoIp-Daten für den Hop" - -[geoip_multiple_data_for_hop] -en = "Multiple GeoIp locations for hop" -fr = "Emplacements GeoIp multiples pour le saut" -tr = "Hop için birden fazla GeoIp konumu" -it = "Posizioni GeoIp multiple per il salto" -pt = "Múltiplas localizações GeoIp para o salto" -zh = "多个 GeoIp 位置" -sv = "Flera GeoIp-platser för hopp" -ru = "Несколько местоположений GeoIp для прыжка" -es = "Múltiples ubicaciones de GeoIp para el salto" -de = "Mehrere GeoIp-Standorte für den Hop" - -[kilometer] -en = "km" -fr = "km" -tr = "km" -it = "km" -pt = "km" -zh = "公里" -sv = "km" -ru = "км" -es = "km" -de = "km" - -[settings_info] -en = "Info" -fr = "Information" -tr = "Bilgi" -it = "Info" -pt = "Informação" -zh = "信息" -sv = "Information" -ru = "Информация" -es = "Información" -de = "Info" - -[settings_tab_tui_title] -en = "Tui" -fr = "Tui" -tr = "Tui" -it = "Tui" -pt = "Tui" -zh = "终端用户界面" -sv = "Tui" -ru = "Tui" -es = "Tui" -de = "Tui" - -[settings_tab_trace_title] -en = "Trace" -fr = "Tracer" -tr = "İz" -it = "Traccia" -pt = "Rastrear" -zh = "跟踪" -sv = "Spåra" -ru = "След" -es = "Rastrear" -de = "Trace" - -[settings_tab_dns_title] -en = "DNS" -fr = "DNS" -tr = "DNS" -it = "DNS" -pt = "DNS" -zh = "DNS" -sv = "DNS" -ru = "DNS" -es = "DNS" -de = "DNS" - -[settings_tab_geoip_title] -en = "GeoIp" -fr = "GeoIp" -tr = "GeoIp" -it = "GeoIp" -pt = "GeoIp" -zh = "GeoIp" -sv = "GeoIp" -ru = "GeoIp" -es = "GeoIp" -de = "GeoIp" - -[settings_tab_bindings_title] -en = "Bindings" -fr = "Raccourcis clavier" -tr = "Bağlantılar" -it = "Collegamenti" -pt = "Atalhos" -zh = "绑定" -sv = "Kortkommando" -ru = "Привязки" -es = "Atajos" -de = "Tastenbelegungen" - -[settings_tab_theme_title] -en = "Theme" -fr = "Thème" -tr = "Tema" -it = "Tema" -pt = "Tema" -zh = "主题" -sv = "Tema" -ru = "Тема" -es = "Tema" -de = "Darstellung" - -[settings_tab_columns_title] -en = "Columns" -fr = "Colonnes" -tr = "Sütunlar" -it = "Colonne" -pt = "Colunas" -zh = "列" -es = "Columnas" -sv = "Kolumner" -ru = "Столбцы" -de = "Spalten" - -[settings_tab_tui_desc] -en = "Settings which control how data is displayed in this Tui" -fr = "Paramètres qui contrôlent la façon dont les données sont affichées dans ce Tui" -tr = "Arayüzde verilerin nasıl görüntülendiğini kontrol eden ayarlar" -it = "Impostazioni che controllano come i dati vengono visualizzati in questo Tui" -pt = "Configurações que controlam como os dados são exibidos neste Tui" -zh = "数据显示方式设置" -sv = "Inställningar som styr hur data visas i detta Tui" -ru = "Настройки, которые контролируют, как данные отображаются в этом Tui" -es = "Configuraciones que controlan cómo se muestran los datos en este Tui" -de = "Einstellungen, die steuern, wie Daten in diesem Tui angezeigt werden" - -[settings_tab_trace_desc] -en = "Settings which control the tracing strategy" -fr = "Paramètres qui contrôlent la stratégie de traçage" -tr = "İzleme stratejisini kontrol eden ayarlar" -it = "Impostazioni che controllano la strategia di tracciamento" -pt = "Configurações que controlam a estratégia de rastreamento" -zh = "跟踪策略设置" -sv = "Inställningar som styr spårningsstrategin" -ru = "Настройки, которые контролируют стратегию трассировки" -es = "Configuraciones que controlan la estrategia de rastreo" -de = "Einstellungen, die die Tracing-Strategie steuern" - -[settings_tab_dns_desc] -en = "Settings which control how DNS lookups are performed" -fr = "Paramètres qui contrôlent la façon dont les recherches DNS sont effectuées" -tr = "DNS aramalarının nasıl yapıldığını kontrol eden ayarlar" -it = "Impostazioni che controllano come vengono eseguite le ricerche DNS" -pt = "Configurações que controlam como as pesquisas DNS são realizadas" -zh = "DNS 查询设置" -sv = "Inställningar som styr hur DNS-uppslag utförs" -ru = "Настройки, которые контролируют, как выполняются DNS-запросы" -es = "Configuraciones que controlan cómo se realizan las búsquedas de DNS" -de = "Einstellungen, die steuern, wie DNS-Lookups durchgeführt werden" - -[settings_tab_geoip_desc] -en = "Settings relating to GeoIp" -fr = "Paramètres relatifs à GeoIp" -tr = "GeoIp ile ilgili ayarlar" -it = "Impostazioni relative a GeoIp" -pt = "Configurações relacionadas ao GeoIp" -zh = "GeoIp 设置" -sv = "Inställningar som rör GeoIp" -ru = "Настройки, касающиеся GeoIp" -es = "Configuraciones relacionadas con GeoIp" -de = "Einstellungen im Zusammenhang mit GeoIp" - -[settings_tab_bindings_desc] -en = "Tui key bindings" -fr = "Raccourcis clavier Tui" -tr = "Tui tuş ayarları" -it = "Collegamenti chiave Tui" -pt = "Atalhos de teclado Tui" -zh = "按键绑定设置" -sv = "Tui-kortkommando" -ru = "Привязки клавиш Tui" -es = "Atajos de teclado Tui" -de = "Tui-Tastenbelegungen" - -[settings_tab_theme_desc] -en = "Tui theme colors" -fr = "Couleurs du thème Tui" -tr = "Tui tema renkleri" -it = "Colori del tema Tui" -pt = "Cores do tema Tui" -zh = "主题颜色设置" -sv = "Tui-temafärger" -ru = "Цвета темы Tui" -es = "Colores del tema Tui" -de = "Tui-Themefarben" - -[settings_tab_columns_desc] -en = "Tui table columns. Press [%{c}] to toggle a column on or off and use the [%{d}] and [%{u}] keys to change the column order." -fr = "Colonnes de table Tui. Appuyez sur [%{c}] pour activer ou désactiver une colonne et utilisez les touches [%{d}] et [%{u}] pour changer l'ordre des colonnes." -tr = "Tui tablo sütunları. Bir sütunu açmak veya kapatmak için [%{c}] tuşuna basın ve sütun sırasını değiştirmek için [%{d}] ve [%{u}] tuşlarını kullanın." -it = "Colonne della tabella Tui. Premi [%{c}] per attivare o disattivare una colonna e usa i tasti [%{d}] e [%{u}] per cambiare l'ordine delle colonne." -pt = "Colunas da tabela Tui. Pressione [%{c}] para ativar ou desativar uma coluna e use as teclas [%{d}] e [%{u}] para alterar a ordem das colunas." -zh = "终端用户界面表格列。按 [%{c}] 切换列的显示和隐藏,使用 [%{d}] 和 [%{u}] 键更改列的顺序。" -sv = "Tui-tabellkolumner. Tryck på [%{c}] för att slå på eller av en kolumn och använd [%{d}] och [%{u}] för att ändra kolumnordningen." -ru = "Столбцы таблицы Tui. Нажмите [%{c}], чтобы включить или отключить столбец, и используйте клавиши [%{d}] и [%{u}], чтобы изменить порядок столбцов." -es = "Columnas de la tabla Tui. Presiona [%{c}] para activar o desactivar una columna y usa las teclas [%{d}] y [%{u}] para cambiar el orden de las columnas." -de = "Tui-Tabellenspalten. Drücken Sie [%{c}], um eine Spalte ein- oder auszuschalten, und verwenden Sie die Tasten [%{d}] und [%{u}], um die Spaltenreihenfolge zu ändern." - -[settings_table_header_setting] -en = "Setting" -fr = "Paramètres" -tr = "Ayar" -it = "Impostazione" -pt = "Configuração" -zh = "设置" -sv = "Inställning" -ru = "Настройка" -es = "Configuración" -de = "Einstellung" - -[settings_table_header_value] -en = "Value" -fr = "Valeur" -tr = "Değer" -it = "Valore" -pt = "Valor" -zh = "值" -sv = "Värde" -ru = "Значение" -es = "Valor" -de = "Wert" - -[column_host] -en = "Host" -fr = "Hôte" -tr = "Ana bilgisayar" -it = "Host" -pt = "Host" -zh = "主机" -sv = "Värd" -ru = "Хост" -es = "Host" -de = "Host" - -[column_loss_pct] -en = "Loss%" -fr = "% Perdus" -tr = "Kayıp%" -it = "Persi%" -pt = "% Perdidos" -zh = "丢包率" -sv = "Förlust%" -ru = "Потери%" -es = "% Perdidos" -de = "Verlust%" - -[column_snd] -en = "Snd" -fr = "Envoyés" -tr = "Gönderilen" -it = "Snd" -pt = "Enviados" -zh = "发出" -sv = "Skickat" -ru = "Отпр" -es = "Enviados" -de = "Snd" - -[column_recv] -en = "Recv" -fr = "Reçus" -tr = "Alınan" -it = "Recv" -pt = "Recebidos" -zh = "接收" -sv = "Mottagna" -ru = "Получ" -es = "Recibidos" -de = "Recv" - -[column_last] -en = "Last" -fr = "Dernier" -tr = "Son" -it = "Ultimo" -pt = "Último" -zh = "最后" -sv = "Senast" -ru = "Посл" -es = "Último" -de = "Letzte" - -[column_avg] -en = "Avg" -fr = "Moyenne" -tr = "Ort" -it = "Media" -pt = "Média" -zh = "平均" -sv = "Genomsnitt" -ru = "Сред" -es = "Prom" -de = "Durchschnitt" - -[column_best] -en = "Best" -fr = "Meilleur" -tr = "En iyi" -it = "Migliore" -pt = "Melhor" -zh = "最佳" -sv = "Bäst" -ru = "Луч" -es = "Mejor" -de = "Beste" - -[column_wrst] -en = "Wrst" -fr = "Pire" -tr = "En kötü" -it = "Peggiore" -pt = "Pior" -zh = "最差" -sv = "Sämst" -ru = "Худ" -es = "Peor" -de = "Schlechteste" - -[column_stdev] -en = "StDev" -fr = "ÉcTyp" -tr = "StDev" -it = "StDev" -pt = "DesvPad" -zh = "标准差" -sv = "StDev" -ru = "СКО" -es = "DesvE" -de = "StdAbw" - -[column_sts] -en = "Sts" -fr = "État" -tr = "Sts" -it = "Stato" -pt = "Est" -zh = "状态" -sv = "Sts" -ru = "Статус" -es = "Est" -de = "Sts" - -[column_jttr] -en = "Jttr" -fr = "Gigue" -tr = "Jttr" -it = "Jttr" -pt = "Jttr" -zh = "抖动" -sv = "Jttr" -ru = "Джитр" -es = "Jttr" -de = "Jttr" - -[column_javg] -en = "Javg" -fr = "GigMoy" -tr = "Javg" -it = "Javg" -pt = "Javg" -zh = "均抖" -sv = "Javg" -ru = "СреднДжитр" -es = "PromJit" -de = "Javg" - -[column_jmax] -en = "Jmax" -fr = "GigMax" -tr = "Jmax" -it = "Jmax" -pt = "Jmax" -zh = "最大抖" -sv = "Jmax" -ru = "МаксДжитр" -es = "JitMax" -de = "Jmax" - -[column_jint] -en = "Jint" -fr = "GigInt" -tr = "Jint" -it = "Jint" -pt = "Jint" -zh = "抖动间隔" -sv = "Jint" -ru = "ИнтДжитр" -es = "JitInt" -de = "Jint" - -[column_sprt] -en = "Sprt" -fr = "Psrc" -tr = "Sprt" -it = "Sprt" -zh = "源端" -sv = "Sprt" -ru = "Исх" -es = "Sprt" -de = "Sprt" - -[column_dprt] -en = "Dprt" -fr = "Pdest" -tr = "Dprt" -it = "Dprt" -pt = "Dprt" -zh = "目标" -sv = "Dprt" -ru = "Назн" -es = "Dprt" -de = "Dprt" - -[column_seq] -en = "Seq" -fr = "Seq" -tr = "Seq" -it = "Seq" -pt = "Seq" -zh = "序列" -sv = "Seq" -ru = "Посл" -es = "Seq" -de = "Seq" - -[column_type] -en = "Type" -fr = "Type" -tr = "Type" -it = "Tipo" -pt = "Tipo" -zh = "类型" -sv = "Typ" -ru = "Тип" -es = "Tipo" -de = "Typ" - -[column_code] -en = "Code" -fr = "Code" -tr = "Code" -it = "Codice" -pt = "Código" -zh = "代码" -sv = "Kod" -ru = "Код" -es = "Código" -de = "Code" - -[column_nat] -en = "Nat" -fr = "Nat" -tr = "Nat" -it = "Nat" -pt = "Nat" -zh = "网络地址转换" -sv = "Nat" -ru = "Nat" -es = "Nat" -de = "Nat" - -[column_fail] -en = "Fail" -fr = "Échec" -tr = "Başarısız" -it = "Falliti" -pt = "Falha" -zh = "失败" -sv = "Misslyckades" -ru = "Неуд" -es = "Falló" -de = "Fehlgeschlagen" - -[column_floss] -en = "Floss" -fr = "Floss" -tr = "Floss" -it = "Floss" -pt = "Floss" -zh = "Floss" -sv = "Floss" -ru = "Floss" -es = "Floss" -de = "Floss" - -[column_bloss] -en = "Bloss" -fr = "Bloss" -tr = "Bloss" -it = "Bloss" -pt = "Bloss" -zh = "Bloss" -sv = "Bloss" -ru = "Bloss" -es = "Bloss" -de = "Bloss" - -[column_floss_pct] -en = "Floss%" -fr = "Floss%" -tr = "Floss%" -it = "Floss%" -pt = "Floss%" -zh = "Floss%" -sv = "Floss%" -ru = "Floss%" -es = "Floss%" -de = "Floss%" diff --git a/crates/trippy-tui/src/app.rs b/crates/trippy-tui/src/app.rs index 77a09ecd..16581d71 100644 --- a/crates/trippy-tui/src/app.rs +++ b/crates/trippy-tui/src/app.rs @@ -1,7 +1,7 @@ use crate::config::{LogFormat, LogSpanEvents, Mode, TrippyConfig}; use crate::frontend::TuiConfig; use crate::geoip::GeoIpLookup; -use crate::locale::{locale, set_locale}; +use crate::locale; use crate::{frontend, report}; use anyhow::{anyhow, Error}; use std::net::IpAddr; @@ -15,8 +15,7 @@ use trippy_privilege::Privilege; /// Run the trippy application. pub fn run_trippy(cfg: &TrippyConfig, pid: u16) -> anyhow::Result<()> { - set_locale(cfg.tui_locale.as_deref()); - let locale = locale(); + let locale = locale::init(cfg.tui_locale.as_deref())?; let _guard = configure_logging(cfg); let resolver = start_dns_resolver(cfg)?; let geoip_lookup = create_geoip_lookup(cfg, &locale)?; diff --git a/crates/trippy-tui/src/frontend/columns.rs b/crates/trippy-tui/src/frontend/columns.rs index 630e2b8b..c02e47f2 100644 --- a/crates/trippy-tui/src/frontend/columns.rs +++ b/crates/trippy-tui/src/frontend/columns.rs @@ -1,7 +1,6 @@ use crate::config::{TuiColumn, TuiColumns}; use crate::t; use ratatui::layout::{Constraint, Rect}; -use std::borrow::Cow; use std::fmt::{Debug, Display, Formatter}; use strum::{EnumIter, IntoEnumIterator}; use unicode_width::UnicodeWidthStr; @@ -136,8 +135,8 @@ pub enum ColumnStatus { impl Display for ColumnStatus { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { match self { - Self::Shown => write!(f, "{}", t!("on")), - Self::Hidden => write!(f, "{}", t!("off")), + Self::Shown => f.write_str(&t!("on")), + Self::Hidden => f.write_str(&t!("off")), } } } @@ -270,9 +269,9 @@ impl Display for ColumnType { impl ColumnType { /// The name of the column in the current locale. #[allow(clippy::cognitive_complexity)] - pub(self) fn name(&self) -> Cow<'_, str> { + pub(self) fn name(self) -> String { match self { - Self::Ttl => Cow::Borrowed("#"), + Self::Ttl => String::from('#'), Self::Host => t!("column_host"), Self::LossPct => t!("column_loss_pct"), Self::Sent => t!("column_snd"), @@ -426,6 +425,7 @@ mod tests { #[test_case(ColumnType::StdDev, "StDev")] #[test_case(ColumnType::Status, "Sts")] fn test_column_display_formatting(c: ColumnType, heading: &'static str) { + let _ = crate::locale::init(Some("en")); assert_eq!(format!("{c}"), heading); } @@ -438,6 +438,7 @@ mod tests { #[test] fn test_column_constraints() { + let _ = crate::locale::init(Some("en")); let columns = Columns::from(TuiColumns::default()); let constraints = columns.constraints(Rect::new(0, 0, 80, 0)); assert_eq!( diff --git a/crates/trippy-tui/src/frontend/render/bar.rs b/crates/trippy-tui/src/frontend/render/bar.rs index a0899d4f..97c6b160 100644 --- a/crates/trippy-tui/src/frontend/render/bar.rs +++ b/crates/trippy-tui/src/frontend/render/bar.rs @@ -5,7 +5,6 @@ use ratatui::layout::{Alignment, Rect}; use ratatui::prelude::{Line, Span, Style}; use ratatui::widgets::Paragraph; use ratatui::Frame; -use std::borrow::Cow; use std::net::IpAddr; use trippy_core::{PrivilegeMode, Protocol}; use trippy_dns::ResolveMethod; @@ -15,18 +14,18 @@ pub fn render(f: &mut Frame<'_>, rect: Rect, app: &TuiApp) { Protocol::Icmp => format!( "{}/{}", fmt_target_family(app.tracer_config().data.target_addr()), - t!("ICMP"), + "ICMP", ), Protocol::Udp => format!( "{}/{}/{}", fmt_target_family(app.tracer_config().data.target_addr()), - t!("UDP"), + "UDP", app.tracer_config().data.multipath_strategy(), ), Protocol::Tcp => format!( "{}/{}", fmt_target_family(app.tracer_config().data.target_addr()), - t!("TCP"), + "TCP", ), }); @@ -111,7 +110,7 @@ pub fn render(f: &mut Frame<'_>, rect: Rect, app: &TuiApp) { f.render_widget(left, rect); } -fn fmt_privilege_mode(privilege_mode: PrivilegeMode) -> Cow<'static, str> { +fn fmt_privilege_mode(privilege_mode: PrivilegeMode) -> String { match privilege_mode { PrivilegeMode::Privileged => t!("privileged"), PrivilegeMode::Unprivileged => t!("unprivileged"), diff --git a/crates/trippy-tui/src/frontend/render/header.rs b/crates/trippy-tui/src/frontend/render/header.rs index a588dafc..00cbbb5f 100644 --- a/crates/trippy-tui/src/frontend/render/header.rs +++ b/crates/trippy-tui/src/frontend/render/header.rs @@ -110,14 +110,15 @@ pub fn render(f: &mut Frame<'_>, app: &TuiApp, rect: Rect) { let flow_count = app.tracer_data().flows().len(); format!( ", {}", - t!("discovered_flows", - "hop_count" => hop_count, - "flow_count" => flow_count, - "plural_flows" => plural_flows + t!( + "discovered_flows", + hop_count = hop_count, + flow_count = flow_count, + plural_flows = plural_flows, ) ) } else { - format!(", {}", t!("discovered", "hop_count" => hop_count)) + format!(", {}", t!("discovered", hop_count = hop_count)) }; let left_line = vec![ Line::from(vec![ @@ -183,7 +184,7 @@ fn render_source(app: &TuiApp) -> String { format_ip(app, addr) } } else { - String::from(t!("unknown")) + t!("unknown") } } @@ -253,16 +254,18 @@ fn render_status(app: &TuiApp) -> String { let failure_rate = format!("{failure_rate:.1}"); format!( " [{}❗]", - t!("status_failures", - "failure_count" => failure_count, - "total_probes" => total_probes, - "failure_rate" => failure_rate) + t!( + "status_failures", + failure_count = failure_count, + total_probes = total_probes, + failure_rate = failure_rate + ) ) } else { String::new() }; if app.selected_tracer_data.error().is_some() { - String::from(t!("status_failed")) + t!("status_failed") } else if let Some(start) = app.frozen_start { let frozen = format_duration(Duration::from_secs( start.elapsed().unwrap_or_default().as_secs(), diff --git a/crates/trippy-tui/src/frontend/render/help.rs b/crates/trippy-tui/src/frontend/render/help.rs index b37cd8a1..7c309ea1 100644 --- a/crates/trippy-tui/src/frontend/render/help.rs +++ b/crates/trippy-tui/src/frontend/render/help.rs @@ -23,9 +23,9 @@ pub fn render(f: &mut Frame<'_>, app: &TuiApp) { Line::raw(r#" "#), Line::raw(t!("help_tagline")), Line::raw(r#" "#), - Line::raw(t!("help_show_settings", key = s)), - Line::raw(t!("help_show_bindings", key = b)), - Line::raw(t!("help_show_columns", key = c)), + Line::raw(t!("help_show_settings", key = s.to_string())), + Line::raw(t!("help_show_bindings", key = b.to_string())), + Line::raw(t!("help_show_columns", key = c.to_string())), Line::raw(r#" "#), Line::raw(r#" https://github.com/fujiapple852/trippy "#), Line::raw(r#" "#), diff --git a/crates/trippy-tui/src/frontend/render/settings.rs b/crates/trippy-tui/src/frontend/render/settings.rs index 49fa5e7c..48d77e8e 100644 --- a/crates/trippy-tui/src/frontend/render/settings.rs +++ b/crates/trippy-tui/src/frontend/render/settings.rs @@ -134,44 +134,43 @@ fn format_all_settings(app: &TuiApp) -> Vec<(String, String, Vec)> let move_up = app.tui_config.bindings.previous_hop_address.to_string(); vec![ ( - t!("settings_tab_tui_title").to_string(), - t!("settings_tab_tui_desc").to_string(), + t!("settings_tab_tui_title"), + t!("settings_tab_tui_desc"), tui_settings, ), ( - t!("settings_tab_trace_title").to_string(), - t!("settings_tab_trace_desc").to_string(), + t!("settings_tab_trace_title"), + t!("settings_tab_trace_desc"), trace_settings, ), ( - t!("settings_tab_dns_title").to_string(), - t!("settings_tab_dns_desc").to_string(), + t!("settings_tab_dns_title"), + t!("settings_tab_dns_desc"), dns_settings, ), ( - t!("settings_tab_geoip_title").to_string(), - t!("settings_tab_geoip_desc").to_string(), + t!("settings_tab_geoip_title"), + t!("settings_tab_geoip_desc"), geoip_settings, ), ( - t!("settings_tab_bindings_title").to_string(), - t!("settings_tab_bindings_desc").to_string(), + t!("settings_tab_bindings_title"), + t!("settings_tab_bindings_desc"), bindings_settings, ), ( - t!("settings_tab_theme_title").to_string(), - t!("settings_tab_theme_desc").to_string(), + t!("settings_tab_theme_title"), + t!("settings_tab_theme_desc"), theme_settings, ), ( - t!("settings_tab_columns_title").to_string(), + t!("settings_tab_columns_title"), t!( "settings_tab_columns_desc", c = toggle_column, d = move_down, u = move_up - ) - .to_string(), + ), columns_settings, ), ] @@ -192,7 +191,7 @@ fn format_tui_settings(app: &TuiApp) -> Vec { "tui-privacy-max-ttl", app.tui_config .privacy_max_ttl - .map_or_else(|| t!("off").to_string(), |m| m.to_string()), + .map_or_else(|| t!("off"), |m| m.to_string()), ), SettingsItem::new( "tui-address-mode", @@ -211,7 +210,7 @@ fn format_tui_settings(app: &TuiApp) -> Vec { "tui-max-addrs", app.tui_config .max_addrs - .map_or_else(|| t!("auto").to_string(), |m| m.to_string()), + .map_or_else(|| t!("auto"), |m| m.to_string()), ), SettingsItem::new( "tui-custom-columns", @@ -226,12 +225,12 @@ fn format_trace_settings(app: &TuiApp) -> Vec { let interface = if let Some(iface) = cfg.data.interface() { iface.to_string() } else { - t!("auto").to_string() + t!("auto") }; let (src_port, dst_port) = match cfg.data.port_direction() { - PortDirection::None => (t!("na").to_string(), t!("na").to_string()), - PortDirection::FixedDest(dst) => (t!("auto").to_string(), format!("{}", dst.0)), - PortDirection::FixedSrc(src) => (format!("{}", src.0), t!("auto").to_string()), + PortDirection::None => (t!("na"), t!("na")), + PortDirection::FixedDest(dst) => (t!("auto"), format!("{}", dst.0)), + PortDirection::FixedSrc(src) => (format!("{}", src.0), t!("auto")), PortDirection::FixedBoth(src, dst) => (format!("{}", src.0), format!("{}", dst.0)), }; vec![ @@ -318,7 +317,7 @@ fn format_geoip_settings(app: &TuiApp) -> Vec { app.tui_config .geoip_mmdb_file .as_deref() - .map_or_else(|| t!("none").to_string(), ToString::to_string), + .map_or_else(|| t!("none"), ToString::to_string), )] } @@ -528,21 +527,21 @@ pub const SETTINGS_TAB_COLUMNS: usize = 6; /// The name and number of items for each tabs in the setting dialog. pub fn settings_tabs() -> [(String, usize); 7] { [ - (t!("settings_tab_tui_title").to_string(), 9), - (t!("settings_tab_trace_title").to_string(), 17), - (t!("settings_tab_dns_title").to_string(), 5), - (t!("settings_tab_geoip_title").to_string(), 1), - (t!("settings_tab_bindings_title").to_string(), 37), - (t!("settings_tab_theme_title").to_string(), 33), - (t!("settings_tab_columns_title").to_string(), 0), + (t!("settings_tab_tui_title"), 9), + (t!("settings_tab_trace_title"), 17), + (t!("settings_tab_dns_title"), 5), + (t!("settings_tab_geoip_title"), 1), + (t!("settings_tab_bindings_title"), 37), + (t!("settings_tab_theme_title"), 33), + (t!("settings_tab_columns_title"), 0), ] } /// The settings table header. pub fn settings_table_header() -> [String; 2] { [ - t!("settings_table_header_setting").to_string(), - t!("settings_table_header_value").to_string(), + t!("settings_table_header_setting"), + t!("settings_table_header_value"), ] } diff --git a/crates/trippy-tui/src/frontend/render/splash.rs b/crates/trippy-tui/src/frontend/render/splash.rs index c7ce0eef..3b04b78d 100644 --- a/crates/trippy-tui/src/frontend/render/splash.rs +++ b/crates/trippy-tui/src/frontend/render/splash.rs @@ -5,7 +5,6 @@ use ratatui::style::Style; use ratatui::text::{Line, Span}; use ratatui::widgets::{Block, BorderType, Borders, Paragraph}; use ratatui::Frame; -use std::borrow::Cow; /// Render the splash screen. /// @@ -25,13 +24,13 @@ pub fn render(f: &mut Frame<'_>, app: &TuiApp, rect: Rect) { .fg(app.tui_config.theme.text), ); #[allow(clippy::needless_raw_string_hashes)] - let splash: Vec> = vec![ + let splash: Vec = vec![ r#" _____ _ "#.into(), r#"|_ _| _(_)_ __ _ __ _ _ "#.into(), r#" | || '_| | '_ \ '_ \ || |"#.into(), r#" |_||_| |_| .__/ .__/\_, |"#.into(), r#" |_| |_| |__/ "#.into(), - "".into(), + String::new(), t!("awaiting_data"), ]; let line: Vec<_> = splash diff --git a/crates/trippy-tui/src/frontend/render/table.rs b/crates/trippy-tui/src/frontend/render/table.rs index c0c69538..32f4ec38 100644 --- a/crates/trippy-tui/src/frontend/render/table.rs +++ b/crates/trippy-tui/src/frontend/render/table.rs @@ -295,7 +295,7 @@ fn render_hostname( } } } else { - (format!("{}", t!("no_response")), 1) + (t!("no_response"), 1) }; (Cell::from(hostname), count) } @@ -522,7 +522,7 @@ fn render_hostname_with_details( format_details(hop, index, dns, geoip_lookup, config) } } else { - format!("{}", t!("no_response")) + t!("no_response") }; (Cell::from(rendered), 7) } diff --git a/crates/trippy-tui/src/frontend/render/world.rs b/crates/trippy-tui/src/frontend/render/world.rs index 677d47a1..c5dcf0d3 100644 --- a/crates/trippy-tui/src/frontend/render/world.rs +++ b/crates/trippy-tui/src/frontend/render/world.rs @@ -150,7 +150,7 @@ fn render_map_info_panel(f: &mut Frame<'_>, app: &TuiApp, rect: Rect, entries: & format!("**{}**", t!("hidden")) } else { match locations.as_slice() { - _ if app.tui_config.geoip_mmdb_file.is_none() => t!("geoip_not_enabled").to_string(), + _ if app.tui_config.geoip_mmdb_file.is_none() => t!("geoip_not_enabled"), [] if selected_hop.addr_count() > 0 => format!( "{} {} ({})", t!("geoip_no_data_for_hop"), diff --git a/crates/trippy-tui/src/lib.rs b/crates/trippy-tui/src/lib.rs index 32835ab9..503afbb5 100644 --- a/crates/trippy-tui/src/lib.rs +++ b/crates/trippy-tui/src/lib.rs @@ -20,9 +20,6 @@ mod print; mod report; mod util; -// initialize the i18n system. -rust_i18n::i18n!("locales", fallback = "en"); - /// Run the Trippy application. pub fn trippy() -> anyhow::Result<()> { let args = Args::parse(); @@ -35,7 +32,7 @@ pub fn trippy() -> anyhow::Result<()> { TrippyAction::PrintConfigTemplate => print::print_config_template(), TrippyAction::PrintManPage => print::print_man_page()?, TrippyAction::PrintShellCompletions(shell) => print::print_shell_completions(shell)?, - TrippyAction::PrintLocales => print::print_locales(), + TrippyAction::PrintLocales => print::print_locales()?, } Ok(()) } diff --git a/crates/trippy-tui/src/locale.rs b/crates/trippy-tui/src/locale.rs index 5739fd0f..9f5aaef0 100644 --- a/crates/trippy-tui/src/locale.rs +++ b/crates/trippy-tui/src/locale.rs @@ -1,58 +1,57 @@ -const FALLBACK_LOCALE: &str = "en"; +use anyhow::Context; +use i18n_embed::unic_langid::LanguageIdentifier; +use i18n_embed::{ + fluent::{fluent_language_loader, FluentLanguageLoader}, + DesktopLanguageRequester, LanguageLoader, LanguageRequester, +}; +use std::str::FromStr; +use std::sync::OnceLock; -/// Set the locale for the application. -/// -/// If the given locale is `None` or unsupported, the system locale is tried. If the system locale -/// is not supported, the fallback locale is used. -/// -/// In both cases, the language part of the locale is used if the full locale is not supported. -pub fn set_locale(locale: Option<&str>) { - if let Some(locale) = locale { - set_locale_inner(locale); - } else if let Some(locale) = sys_locale::get_locale().as_ref() { - set_locale_inner(locale); - } else { - set_locale_inner(FALLBACK_LOCALE); - } +/// Get all available locales. +pub fn available_languages() -> anyhow::Result> { + Ok(__language_loader() + .available_languages(&Localizations)? + .iter() + .map(ToString::to_string) + .collect()) } -/// Get the current locale. -pub fn locale() -> String { - rust_i18n::locale().to_string() +/// Initialize the locale. +pub fn init(cfg_locale: Option<&str>) -> anyhow::Result { + let cfg_locale = cfg_locale + .map(LanguageIdentifier::from_str) + .transpose() + .context("failed to parse locale")?; + let requested = cfg_locale + .into_iter() + .chain(DesktopLanguageRequester::new().requested_languages()) + .collect::>(); + let selected = i18n_embed::select(__language_loader(), &Localizations, &requested)?; + Ok(selected + .first() + .map_or_else(|| String::from(FALLBACK_LOCALE), ToString::to_string)) } -/// Get all available locales. -pub fn available_locales() -> Vec<&'static str> { - rust_i18n::available_locales!() -} +const FALLBACK_LOCALE: &str = "en"; -fn set_locale_inner(locale: &str) { - let all_locales = rust_i18n::available_locales!(); - if all_locales.contains(&locale) { - rust_i18n::set_locale(locale); - } else { - let language = split_locale(locale); - if all_locales.contains(&language.as_str()) { - rust_i18n::set_locale(&language); - } else { - rust_i18n::set_locale(FALLBACK_LOCALE); - } - } -} +static LANGUAGE_LOADER: OnceLock = OnceLock::new(); + +#[derive(rust_embed::RustEmbed)] +#[folder = "i18n"] +struct Localizations; -fn split_locale(locale: &str) -> String { - let mut parts = locale.split(['-', '_']); - parts - .next() - .map_or_else(|| FALLBACK_LOCALE, |lang| lang) - .to_string() +// this needs to be public for the macro to work, however it should be considered private and not +// used directly. +#[doc(hidden)] +pub fn __language_loader() -> &'static FluentLanguageLoader { + LANGUAGE_LOADER.get_or_init(|| fluent_language_loader!()) } -// A macro for translating a text string. +// A wrapper macro for translating a text string. #[macro_export] macro_rules! t { ($($all:tt)*) => { - rust_i18n::t!($($all)*) + i18n_embed_fl::fl!($crate::locale::__language_loader(), $($all)*) } } @@ -61,20 +60,23 @@ mod tests { use super::*; #[test] - fn test_split_locale_dash() { - let language = split_locale("en-US"); - assert_eq!(language, "en"); - } - - #[test] - fn test_split_locale_underscore() { - let language = split_locale("en_US"); - assert_eq!(language, "en"); + fn test_available_languages() { + assert_eq!( + available_languages().unwrap(), + vec!["de", "en", "es", "fr", "it", "pt", "ru", "sv", "tr", "zh"] + ); } #[test] - fn test_split_locale_no_region() { - let language = split_locale("en"); - assert_eq!(language, "en"); + fn test_init() { + assert!(init(None).is_ok()); + assert_eq!(init(Some("en")).unwrap(), "en"); + assert_eq!(init(Some("zh")).unwrap(), "zh"); + assert_eq!(init(Some("en-US")).unwrap(), "en"); + assert_eq!(init(Some("en-xx")).unwrap(), "en"); + assert_eq!(init(Some("zh_hk")).unwrap(), "zh"); + assert_eq!(init(Some("zh_xx")).unwrap(), "zh"); + assert!(init(Some("en-x")).is_err()); + assert!(init(Some("en-")).is_err()); } } diff --git a/crates/trippy-tui/src/print.rs b/crates/trippy-tui/src/print.rs index ce14aa2c..05ae9bc7 100644 --- a/crates/trippy-tui/src/print.rs +++ b/crates/trippy-tui/src/print.rs @@ -1,5 +1,4 @@ use crate::config::{Args, TuiCommandItem, TuiThemeItem}; -use crate::locale::available_locales; use clap::CommandFactory; use clap_complete::Shell; use itertools::Itertools; @@ -31,8 +30,9 @@ pub fn print_man_page() -> anyhow::Result<()> { process::exit(0); } -pub fn print_locales() { - println!("TUI locales: {}", available_locales().iter().join(", ")); +pub fn print_locales() -> anyhow::Result<()> { + let locales = crate::locale::available_languages()?; + println!("TUI locales: {}", locales.iter().join(", ")); process::exit(0); }