diff --git a/Cargo.lock b/Cargo.lock index 7af21535c61..d5643e8b607 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -121,9 +121,9 @@ dependencies = [ [[package]] name = "anyhow" -version = "1.0.97" +version = "1.0.98" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dcfed56ad506cb2c684a14971b8861fdc3baaaae314b9e5f9bb532cbe3ba7a4f" +checksum = "e16d2d3311acee920a9eb8d33b8cbc1787ce4a264e85f964c2404b969bdcd487" [[package]] name = "approx" @@ -136,19 +136,21 @@ dependencies = [ [[package]] name = "arboard" -version = "3.4.1" +version = "3.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df099ccb16cd014ff054ac1bf392c67feeef57164b05c42f037cd40f5d4357f4" +checksum = "c1df21f715862ede32a0c525ce2ca4d52626bb0007f8c18b87a384503ac33e70" dependencies = [ "clipboard-win", - "core-graphics", "image", "log", "objc2", "objc2-app-kit", + "objc2-core-foundation", + "objc2-core-graphics", "objc2-foundation", "parking_lot", - "windows-sys 0.48.0", + "percent-encoding", + "windows-sys 0.59.0", "wl-clipboard-rs", "x11rb", ] @@ -242,6 +244,8 @@ dependencies = [ "fs-err 2.11.0", "futures-util", "fuzzy-matcher", + "i18n-embed", + "i18n-embed-fl", "indicatif", "interim", "itertools 0.13.0", @@ -250,6 +254,7 @@ dependencies = [ "regex", "rpassword", "runtime-format", + "rust-embed", "rustix 0.38.44", "semver", "serde", @@ -272,6 +277,7 @@ version = "18.5.0" dependencies = [ "async-trait", "atuin-common", + "atuin-macro", "base64 0.22.1", "clap", "config", @@ -325,19 +331,27 @@ dependencies = [ name = "atuin-common" version = "18.5.0" dependencies = [ + "atuin-macro", "base64 0.22.1", "directories", "eyre", "getrandom 0.2.15", + "i18n-embed", + "i18n-embed-fl", "lazy_static", + "paste", "pretty_assertions", + "rust-embed", "semver", "serde", + "slugify", "sqlx", + "sys-locale", "sysinfo", "thiserror 1.0.69", "time", "typed-builder", + "unic-langid", "uuid", ] @@ -395,6 +409,34 @@ dependencies = [ "unicode-segmentation", ] +[[package]] +name = "atuin-macro" +version = "18.5.0" +dependencies = [ + "base64 0.22.1", + "directories", + "eyre", + "getrandom 0.2.15", + "i18n-embed", + "i18n-embed-fl", + "lazy_static", + "paste", + "proc-macro2", + "quote", + "rust-embed", + "semver", + "serde", + "slugify", + "sqlx", + "syn", + "sys-locale", + "sysinfo", + "thiserror 1.0.69", + "time", + "typed-builder", + "uuid", +] + [[package]] name = "atuin-scripts" version = "18.5.0" @@ -435,7 +477,7 @@ dependencies = [ "postmark", "rand 0.8.5", "reqwest 0.11.27", - "rustls 0.23.25", + "rustls 0.23.26", "semver", "serde", "serde_json", @@ -551,7 +593,7 @@ dependencies = [ "hyper 1.6.0", "hyper-util", "pin-project-lite", - "rustls 0.23.25", + "rustls 0.23.26", "rustls-pemfile 2.2.0", "rustls-pki-types", "tokio", @@ -592,6 +634,15 @@ version = "1.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "89e25b6adfb930f02d1981565a6e5d9c547ac15a96606256d3b59040e5cd4ca3" +[[package]] +name = "basic-toml" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a" +dependencies = [ + "serde", +] + [[package]] name = "beef" version = "0.5.2" @@ -622,6 +673,12 @@ dependencies = [ "digest", ] +[[package]] +name = "block" +version = "0.1.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" + [[package]] name = "block-buffer" version = "0.10.4" @@ -631,15 +688,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "block2" -version = "0.5.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2c132eebf10f5cad5289222520a4a058514204aed6d791f1cf4fe8088b82d15f" -dependencies = [ - "objc2", -] - [[package]] name = "bumpalo" version = "3.17.0" @@ -693,9 +741,9 @@ dependencies = [ [[package]] name = "cc" -version = "1.2.16" +version = "1.2.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be714c154be609ec7f5dad223a33bf1482fff90472de28f7362806e6d4832b8c" +checksum = "8e3a13707ac958681c13b39b458c073d0d9bc8a22cb1b2f4c8e55eb72c13f362" dependencies = [ "shlex", ] @@ -706,12 +754,6 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" -[[package]] -name = "cfg_aliases" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd16c4719339c4530435d38e511904438d07cce7950afa3718a84ac36c10e89e" - [[package]] name = "cfg_aliases" version = "0.2.1" @@ -755,9 +797,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.32" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6088f3ae8c3608d19260cd7445411865a485688711b78b5be70d78cd96136f83" +checksum = "eccb054f56cbd38340b380d4a8e69ef1f02f1af43db2f0cc817a4774d80ae071" dependencies = [ "clap_builder", "clap_derive", @@ -765,9 +807,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.32" +version = "4.5.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22a7ef7f676155edfb82daa97f99441f3ebf4a58d5e32f295a56259f1b6facc8" +checksum = "efd9466fac8543255d3b1fcad4762c5e116ffe808c8a3043d4263cd4fd4862a2" dependencies = [ "anstream", "anstyle", @@ -778,9 +820,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.5.46" +version = "4.5.47" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f5c5508ea23c5366f77e53f5a0070e5a84e51687ec3ef9e0464c86dc8d13ce98" +checksum = "c06f5378ea264ad4f82bbc826628b5aad714a75abf6ece087e923010eb937fb6" dependencies = [ "clap", ] @@ -875,7 +917,7 @@ checksum = "595aae20e65c3be792d05818e8c63025294ac3cb7e200f11459063a352a6ef80" dependencies = [ "pathdiff", "serde", - "toml", + "toml 0.8.20", "winnow", ] @@ -914,30 +956,6 @@ version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" -[[package]] -name = "core-graphics" -version = "0.23.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c07782be35f9e1140080c6b96f0d44b739e2278479f64e02fdab4e32dfd8b081" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "core-graphics-types", - "foreign-types", - "libc", -] - -[[package]] -name = "core-graphics-types" -version = "0.1.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45390e6114f68f718cc7a830514a96f903cccd70d02a8f6d9f643ac4ba45afaf" -dependencies = [ - "bitflags 1.3.2", - "core-foundation", - "libc", -] - [[package]] name = "cpufeatures" version = "0.2.17" @@ -1087,9 +1105,9 @@ dependencies = [ [[package]] name = "darling" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6f63b86c8a8826a49b8c21f08a2d07338eec8d900540f8630dc76284be802989" +checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee" dependencies = [ "darling_core", "darling_macro", @@ -1097,9 +1115,9 @@ dependencies = [ [[package]] name = "darling_core" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "95133861a8032aaea082871032f5815eb9e98cef03fa916ab4500513994df9e5" +checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e" dependencies = [ "fnv", "ident_case", @@ -1111,9 +1129,9 @@ dependencies = [ [[package]] name = "darling_macro" -version = "0.20.10" +version = "0.20.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d336a2a514f6ccccaa3e09b02d41d35330c07ddf03a62165fcec10bb561c7806" +checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead" dependencies = [ "darling_core", "quote", @@ -1135,9 +1153,9 @@ dependencies = [ [[package]] name = "der" -version = "0.7.9" +version = "0.7.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f55bf8e7b65898637379c1b74eb1551107c8294ed26d855ceb9fd1a09cfc9bc0" +checksum = "e7c1832837b905bbfb5101e07cc24c8deddf52f93225eee6ead5f4d63d53ddcb" dependencies = [ "const-oid", "pem-rfc7468", @@ -1154,17 +1172,6 @@ dependencies = [ "serde", ] -[[package]] -name = "derive-new" -version = "0.6.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d150dea618e920167e5973d70ae6ece4385b7164e0d799fe7c122dd0a5d912ad" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "diff" version = "0.1.13" @@ -1189,16 +1196,16 @@ version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9a49173b84e034382284f27f1af4dcbbd231ffa358c0fe316541a7337f376a35" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.1", ] [[package]] name = "dirs" -version = "5.0.1" +version = "6.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" +checksum = "c3e8aa94d75141228480295a7d0e7feb620b1a5ad9f12bc40be62411e38cce4e" dependencies = [ - "dirs-sys", + "dirs-sys 0.5.0", ] [[package]] @@ -1209,10 +1216,32 @@ checksum = "520f05a5cbd335fae5a99ff7a6ab8627577660ee5cfd6a94a6a929b52ff0321c" dependencies = [ "libc", "option-ext", - "redox_users", + "redox_users 0.4.6", "windows-sys 0.48.0", ] +[[package]] +name = "dirs-sys" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e01a3366d27ee9890022452ee61b2b63a67e6f13f58900b651ff5665f0bb1fab" +dependencies = [ + "libc", + "option-ext", + "redox_users 0.5.0", + "windows-sys 0.59.0", +] + +[[package]] +name = "dispatch2" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "89a09f22a6c6069a18470eb92d2298acf25463f14256d24778e1230d789a2aec" +dependencies = [ + "bitflags 2.9.0", + "objc2", +] + [[package]] name = "displaydoc" version = "0.2.5" @@ -1226,9 +1255,9 @@ dependencies = [ [[package]] name = "divan" -version = "0.1.17" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0583193020b29b03682d8d33bb53a5b0f50df6daacece12ca99b904cfdcb8c4" +checksum = "a405457ec78b8fe08b0e32b4a3570ab5dff6dd16eb9e76a5ee0a9d9cbd898933" dependencies = [ "cfg-if", "clap", @@ -1240,9 +1269,9 @@ dependencies = [ [[package]] name = "divan-macros" -version = "0.1.17" +version = "0.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8dc51d98e636f5e3b0759a39257458b22619cac7e96d932da6eeb052891bb67c" +checksum = "9556bc800956545d6420a640173e5ba7dfa82f38d3ea5a167eb555bc69ac3323" dependencies = [ "proc-macro2", "quote", @@ -1317,9 +1346,9 @@ checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" [[package]] name = "errno" -version = "0.3.10" +version = "0.3.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "33d852cb9b869c2a9b3df2f71a3074817f01e1844f839a144f5fcef059a4eb5d" +checksum = "976dd42dc7e85965fe702eb8164f21f450704bdde31faefd6471dba214cb594e" dependencies = [ "libc", "windows-sys 0.59.0", @@ -1401,6 +1430,15 @@ dependencies = [ "winapi", ] +[[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" @@ -1415,63 +1453,80 @@ checksum = "1d674e81391d1e1ab681a28d99df07927c6d4aa5b027d7da16ba32d1d21ecd99" [[package]] name = "flate2" -version = "1.1.0" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "11faaf5a5236997af9848be0bef4db95824b1d534ebc64d0f0c6cf3e67bd38dc" +checksum = "7ced92e76e966ca2fd84c8f7aa01a4aea65b0eb6648d72f7c8f3e2764a67fece" dependencies = [ "crc32fast", "miniz_oxide", ] [[package]] -name = "flume" -version = "0.11.1" +name = "fluent" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" +checksum = "bb74634707bebd0ce645a981148e8fb8c7bccd4c33c652aeffd28bf2f96d555a" dependencies = [ - "futures-core", - "futures-sink", - "spin", + "fluent-bundle", + "unic-langid", ] [[package]] -name = "fnv" -version = "1.0.7" +name = "fluent-bundle" +version = "0.15.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +checksum = "7fe0a21ee80050c678013f82edf4b705fe2f26f1f9877593d13198612503f493" +dependencies = [ + "fluent-langneg", + "fluent-syntax", + "intl-memoizer", + "intl_pluralrules", + "rustc-hash 1.1.0", + "self_cell 0.10.3", + "smallvec", + "unic-langid", +] [[package]] -name = "foldhash" -version = "0.1.5" +name = "fluent-langneg" +version = "0.13.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" +checksum = "2c4ad0989667548f06ccd0e306ed56b61bd4d35458d54df5ec7587c0e8ed5e94" +dependencies = [ + "unic-langid", +] [[package]] -name = "foreign-types" -version = "0.5.0" +name = "fluent-syntax" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d737d9aa519fb7b749cbc3b962edcf310a8dd1f4b67c91c4f83975dbdd17d965" +checksum = "2a530c4694a6a8d528794ee9bbd8ba0122e779629ac908d15ad5a7ae7763a33d" dependencies = [ - "foreign-types-macros", - "foreign-types-shared", + "thiserror 1.0.69", ] [[package]] -name = "foreign-types-macros" -version = "0.2.3" +name = "flume" +version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1a5c6c585bc94aaf2c7b51dd4c2ba22680844aba4c687be581871a6f518c5742" +checksum = "da0e4dd2a88388a1f4ccc7c9ce104604dab68d9f408dc34cd45823d5a9069095" dependencies = [ - "proc-macro2", - "quote", - "syn", + "futures-core", + "futures-sink", + "spin", ] [[package]] -name = "foreign-types-shared" -version = "0.3.1" +name = "fnv" +version = "1.0.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" + +[[package]] +name = "foldhash" +version = "0.1.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "aa9a19cbb55df58761df49b23516a86d432839add4af60fc256da840f66ed35b" +checksum = "d9c4f5dac5e15c24eb999c26181a6ca40b39fe946cbe4c263c7209467bc83af2" [[package]] name = "form_urlencoded" @@ -1677,7 +1732,7 @@ dependencies = [ "futures-sink", "futures-util", "http 0.2.12", - "indexmap 2.8.0", + "indexmap 2.9.0", "slab", "tokio", "tokio-util", @@ -1686,9 +1741,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.4.8" +version = "0.4.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5017294ff4bb30944501348f6f8e42e6ad28f42c8bbef7a74029aff064a4e3c2" +checksum = "75249d144030531f8dee69fe9cea04d3edf809a017ae445e2abdff6629e86633" dependencies = [ "atomic-waker", "bytes", @@ -1696,7 +1751,7 @@ dependencies = [ "futures-core", "futures-sink", "http 1.3.1", - "indexmap 2.8.0", + "indexmap 2.9.0", "slab", "tokio", "tokio-util", @@ -1896,7 +1951,7 @@ dependencies = [ "bytes", "futures-channel", "futures-util", - "h2 0.4.8", + "h2 0.4.9", "http 1.3.1", "http-body 1.0.1", "httparse", @@ -1932,7 +1987,7 @@ dependencies = [ "http 1.3.1", "hyper 1.6.0", "hyper-util", - "rustls 0.23.25", + "rustls 0.23.26", "rustls-pki-types", "tokio", "tokio-rustls 0.26.2", @@ -1955,9 +2010,9 @@ dependencies = [ [[package]] name = "hyper-util" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "df2dcfbe0677734ab2f3ffa7fa7bfd4706bfdc1ef393f2ee30184aed67e631b4" +checksum = "497bbc33a26fdd4af9ed9c70d63f61cf56a938375fbb32df34db9b1cd6d643f2" dependencies = [ "bytes", "futures-channel", @@ -1965,6 +2020,7 @@ dependencies = [ "http 1.3.1", "http-body 1.0.1", "hyper 1.6.0", + "libc", "pin-project-lite", "socket2", "tokio", @@ -1972,18 +2028,87 @@ dependencies = [ "tracing", ] +[[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.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "669ffc2c93f97e6ddf06ddbe999fcd6782e3342978bb85f7d3c087c7978404c4" +dependencies = [ + "arc-swap", + "fluent", + "fluent-langneg", + "fluent-syntax", + "i18n-embed-impl", + "intl-memoizer", + "locale_config", + "log", + "parking_lot", + "rust-embed", + "thiserror 1.0.69", + "tr", + "unic-langid", + "walkdir", +] + +[[package]] +name = "i18n-embed-fl" +version = "0.9.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "04b2969d0b3fc6143776c535184c19722032b43e6a642d710fa3f88faec53c2d" +dependencies = [ + "find-crate", + "fluent", + "fluent-syntax", + "i18n-config", + "i18n-embed", + "proc-macro-error2", + "proc-macro2", + "quote", + "strsim", + "syn", + "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", +] + [[package]] name = "iana-time-zone" -version = "0.1.61" +version = "0.1.63" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "235e081f3925a06703c2d0117ea8b91f042756fd6e7a6e5d901e8ca1a996b220" +checksum = "b0c919e5debc312ad217002b8048a17b7d83f80703865bbfcfebb0458b0b27d8" dependencies = [ "android_system_properties", "core-foundation-sys", "iana-time-zone-haiku", "js-sys", + "log", "wasm-bindgen", - "windows-core", + "windows-core 0.61.0", ] [[package]] @@ -2036,9 +2161,9 @@ dependencies = [ [[package]] name = "icu_locid_transform_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdc8ff3388f852bede6b579ad4e978ab004f139284d7b28715f773507b946f6e" +checksum = "7515e6d781098bf9f7205ab3fc7e9709d34554ae0b21ddbcb5febfa4bc7df11d" [[package]] name = "icu_normalizer" @@ -2060,9 +2185,9 @@ dependencies = [ [[package]] name = "icu_normalizer_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8cafbf7aa791e9b22bec55a167906f9e1215fd475cd22adfcf660e03e989516" +checksum = "c5e8338228bdc8ab83303f16b797e177953730f601a96c25d10cb3ab0daa0cb7" [[package]] name = "icu_properties" @@ -2081,9 +2206,9 @@ dependencies = [ [[package]] name = "icu_properties_data" -version = "1.5.0" +version = "1.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67a8effbc3dd3e4ba1afa8ad918d5684b8868b3b26500753effea8d2eed19569" +checksum = "85fb8799753b75aee8d2a21d7c14d9f38921b54b3dbda10f5a3c7a7b82dba5e2" [[package]] name = "icu_provider" @@ -2142,9 +2267,9 @@ dependencies = [ [[package]] name = "image" -version = "0.25.5" +version = "0.25.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd6f44aed642f18953a158afeb30206f4d50da59fbc66ecb53c66488de73563b" +checksum = "db35664ce6b9810857a38a906215e75a9c879f0696556a39f59c62829710251a" dependencies = [ "bytemuck", "byteorder-lite", @@ -2172,9 +2297,9 @@ dependencies = [ [[package]] name = "indexmap" -version = "2.8.0" +version = "2.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3954d50fe15b02142bf25d3b8bdadb634ec3948f103d04ffe3031bc8fe9d7058" +checksum = "cea70ddb795996207ad57735b50c5982d8844f38ba9ee5f1aedcfb708a2aa11e" dependencies = [ "equivalent", "hashbrown 0.15.2", @@ -2232,6 +2357,25 @@ dependencies = [ "time", ] +[[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 = "ipnet" version = "2.11.0" @@ -2304,9 +2448,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.171" +version = "0.2.172" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c19937216e9d3aa9956d9bb8dfc0b0c8beb6058fc4f7a4dc4d850edf86a237d6" +checksum = "d750af042f7ef4f724306de029d18836c26c1765a54a6a3f094cbd23a7267ffa" [[package]] name = "libm" @@ -2343,9 +2487,9 @@ checksum = "d26c52dbd32dccf2d10cac7725f8eae5296885fb5703b261f7d0a0739ec807ab" [[package]] name = "linux-raw-sys" -version = "0.9.3" +version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe7db12097d22ec582439daf8618b8fdd1a7bef6270e9af3b1ebcd30893cf413" +checksum = "cd945864f07fe9f5371a27ad7b52a172b4b499999f1d97574c9fa68373937e12" [[package]] name = "listenfd" @@ -2364,6 +2508,19 @@ version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "23fb14cb19457329c82206317a5663005a4d404783dc74f4252769b0d5f42856" +[[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" @@ -2376,9 +2533,9 @@ dependencies = [ [[package]] name = "log" -version = "0.4.26" +version = "0.4.27" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30bde2b3dc3671ae49d8e2e9f044c7c005836e7a023ee57cffa25ab82764bb9e" +checksum = "13dc2df351e3202783a1fe0d44375f7295ffb4049267b0f3018346dc122a1d94" [[package]] name = "logos" @@ -2432,6 +2589,15 @@ dependencies = [ "libc", ] +[[package]] +name = "malloc_buf" +version = "0.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb" +dependencies = [ + "libc", +] + [[package]] name = "matchers" version = "0.1.0" @@ -2564,9 +2730,9 @@ checksum = "68354c5c6bd36d73ff3feceb05efa59b6acb7626617f4962be322a825e61f79a" [[package]] name = "miniz_oxide" -version = "0.8.5" +version = "0.8.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e3e04debbb59698c15bacbb6d93584a8c0ca9cc3213cb423d31f760d8843ce5" +checksum = "3be647b768db090acb35d5ec5db2b0e1f1de11133ca123b9eacf5137868f892a" dependencies = [ "adler2", "simd-adler32", @@ -2596,18 +2762,6 @@ version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "defc4c55412d89136f966bbb339008b474350e5e6e78d2714439c386b3137a03" -[[package]] -name = "nix" -version = "0.28.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ab2156c4fce2f8df6c499cc1c763e4394b7482525bf2a9701c9d79d215f519e4" -dependencies = [ - "bitflags 2.9.0", - "cfg-if", - "cfg_aliases 0.1.1", - "libc", -] - [[package]] name = "nom" version = "7.1.3" @@ -2734,59 +2888,68 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "830b246a0e5f20af87141b25c173cd1b609bd7779a4617d6ec582abaf90870f3" [[package]] -name = "objc-sys" -version = "0.3.5" +name = "objc" +version = "0.2.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cdb91bdd390c7ce1a8607f35f3ca7151b65afc0ff5ff3b34fa350f7d7c7e4310" +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 = "objc2" -version = "0.5.2" +version = "0.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46a785d4eeff09c14c487497c162e92766fbb3e4059a71840cecc03d9a50b804" +checksum = "88c6597e14493ab2e44ce58f2fdecf095a51f12ca57bec060a11c57332520551" dependencies = [ - "objc-sys", "objc2-encode", ] [[package]] name = "objc2-app-kit" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4e89ad9e3d7d297152b17d39ed92cd50ca8063a89a9fa569046d41568891eff" +checksum = "e6f29f568bec459b0ddff777cec4fe3fd8666d82d5a40ebd0ff7e66134f89bcc" dependencies = [ "bitflags 2.9.0", - "block2", - "libc", "objc2", - "objc2-core-data", - "objc2-core-image", + "objc2-core-graphics", "objc2-foundation", - "objc2-quartz-core", ] [[package]] -name = "objc2-core-data" -version = "0.2.2" +name = "objc2-core-foundation" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "617fbf49e071c178c0b24c080767db52958f716d9eabdf0890523aeae54773ef" +checksum = "1c10c2894a6fed806ade6027bcd50662746363a9589d3ec9d9bef30a4e4bc166" dependencies = [ "bitflags 2.9.0", - "block2", + "dispatch2", "objc2", - "objc2-foundation", ] [[package]] -name = "objc2-core-image" -version = "0.2.2" +name = "objc2-core-graphics" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "55260963a527c99f1819c4f8e3b47fe04f9650694ef348ffd2227e8196d34c80" +checksum = "989c6c68c13021b5c2d6b71456ebb0f9dc78d752e86a98da7c716f4f9470f5a4" dependencies = [ - "block2", + "bitflags 2.9.0", + "dispatch2", "objc2", - "objc2-foundation", - "objc2-metal", + "objc2-core-foundation", + "objc2-io-surface", ] [[package]] @@ -2797,39 +2960,33 @@ checksum = "ef25abbcd74fb2609453eb695bd2f860d389e457f67dc17cafc8b8cbc89d0c33" [[package]] name = "objc2-foundation" -version = "0.2.2" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0ee638a5da3799329310ad4cfa62fbf045d5f56e3ef5ba4149e7452dcf89d5a8" +checksum = "900831247d2fe1a09a683278e5384cfb8c80c79fe6b166f9d14bfdde0ea1b03c" dependencies = [ "bitflags 2.9.0", - "block2", - "libc", "objc2", + "objc2-core-foundation", ] [[package]] -name = "objc2-metal" -version = "0.2.2" +name = "objc2-io-surface" +version = "0.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dd0cba1276f6023976a406a14ffa85e1fdd19df6b0f737b063b95f6c8c7aadd6" +checksum = "7282e9ac92529fa3457ce90ebb15f4ecbc383e8338060960760fa2cf75420c3c" dependencies = [ "bitflags 2.9.0", - "block2", "objc2", - "objc2-foundation", + "objc2-core-foundation", ] [[package]] -name = "objc2-quartz-core" -version = "0.2.2" +name = "objc_id" +version = "0.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e42bee7bff906b14b167da2bac5efe6b6a07e6f7c0a21a7308d40c960242dc7a" +checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b" dependencies = [ - "bitflags 2.9.0", - "block2", - "objc2", - "objc2-foundation", - "objc2-metal", + "objc", ] [[package]] @@ -2843,9 +3000,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.21.1" +version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d75b0bedcc4fe52caa0e03d9f1151a323e4aa5e2d78ba3580400cd3c9e2bc4bc" +checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" [[package]] name = "opaque-debug" @@ -2989,7 +3146,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b4c5cc86750666a3ed20bdaf5ca2a0344f9c67674cae0515bec2da16fbaa47db" dependencies = [ "fixedbitset 0.4.2", - "indexmap 2.8.0", + "indexmap 2.9.0", ] [[package]] @@ -2999,7 +3156,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3672b37090dbd86368a4145bc067582552b29c27377cad4e0a306c97f9bd7772" dependencies = [ "fixedbitset 0.5.7", - "indexmap 2.8.0", + "indexmap 2.9.0", ] [[package]] @@ -3162,7 +3319,7 @@ version = "0.2.21" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "85eae3c4ed2f50dcfe72643da4befc30deadb458a9b590d720cde2f2b1e97da9" dependencies = [ - "zerocopy 0.8.23", + "zerocopy 0.8.24", ] [[package]] @@ -3177,19 +3334,41 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.31" +version = "0.2.32" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5316f57387668042f561aae71480de936257848f9c43ce528e311d89a07cadeb" +checksum = "664ec5419c51e34154eec046ebcba56312d5a2fc3b09a06da188e1ad21afadf6" dependencies = [ "proc-macro2", "syn", ] +[[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", +] + [[package]] name = "proc-macro2" -version = "1.0.94" +version = "1.0.95" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31971752e70b8b2686d7e46ec17fb38dad4051d94024c88df49b667caea9c84" +checksum = "02b3e5e68a3a1a02aad3ec490a98007cbc13c37cbe84a3cd7b8e406d76e7f778" dependencies = [ "unicode-ident", ] @@ -3239,9 +3418,9 @@ dependencies = [ [[package]] name = "prost-reflect" -version = "0.15.0" +version = "0.15.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4fc3f7beed65794248634d530bbb3e2c2abc416d952b973755659938e3c51eac" +checksum = "ebb644dd3ad12d7cf62a18234d385ea5511ac6abb208704c18098e7e3a5e1b69" dependencies = [ "logos", "miette", @@ -3303,9 +3482,9 @@ dependencies = [ [[package]] name = "quick-xml" -version = "0.37.2" +version = "0.37.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "165859e9e55f79d67b96c5d96f4e88b6f2695a1972849c15a6a3f5c59fc2c003" +checksum = "a4ce8c88de324ff838700f36fb6ab86c96df0e3c4ab6ef3a9b2044465cce1369" dependencies = [ "memchr", ] @@ -3317,12 +3496,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012" dependencies = [ "bytes", - "cfg_aliases 0.2.1", + "cfg_aliases", "pin-project-lite", "quinn-proto", "quinn-udp", "rustc-hash 2.1.1", - "rustls 0.23.25", + "rustls 0.23.26", "socket2", "thiserror 2.0.12", "tokio", @@ -3338,10 +3517,10 @@ checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc" dependencies = [ "bytes", "getrandom 0.3.2", - "rand 0.9.0", + "rand 0.9.1", "ring", "rustc-hash 2.1.1", - "rustls 0.23.25", + "rustls 0.23.26", "rustls-pki-types", "slab", "thiserror 2.0.12", @@ -3352,11 +3531,11 @@ dependencies = [ [[package]] name = "quinn-udp" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944" +checksum = "541d0f57c6ec747a90738a52741d3221f7960e8ac2f0ff4b1a63680e033b4ab5" dependencies = [ - "cfg_aliases 0.2.1", + "cfg_aliases", "libc", "once_cell", "socket2", @@ -3392,13 +3571,12 @@ dependencies = [ [[package]] name = "rand" -version = "0.9.0" +version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3779b94aeb87e8bd4e834cee3650289ee9e0d5677f976ecdb6d219e5f4f6cd94" +checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97" dependencies = [ "rand_chacha 0.9.0", "rand_core 0.9.3", - "zerocopy 0.8.23", ] [[package]] @@ -3491,9 +3669,9 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.5.10" +version = "0.5.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0b8c0c260b63a8219631167be35e6a988e9554dbd323f8bd08439c8ed1302bd1" +checksum = "d2f103c6d277498fbceb16e84d317e2a400f160f46904d5f5410848c829511a3" dependencies = [ "bitflags 2.9.0", ] @@ -3509,6 +3687,17 @@ dependencies = [ "thiserror 1.0.69", ] +[[package]] +name = "redox_users" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd6f9d3d47bdd2ad6945c5015a226ec6155d0bcdfd8f7cd29f86b71f8de99d2b" +dependencies = [ + "getrandom 0.2.15", + "libredox", + "thiserror 2.0.12", +] + [[package]] name = "regex" version = "1.11.1" @@ -3624,7 +3813,7 @@ dependencies = [ "percent-encoding", "pin-project-lite", "quinn", - "rustls 0.23.25", + "rustls 0.23.26", "rustls-pemfile 2.2.0", "rustls-pki-types", "serde", @@ -3670,13 +3859,13 @@ dependencies = [ [[package]] name = "rpassword" -version = "7.3.1" +version = "7.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80472be3c897911d0137b2d2b9055faf6eeac5b14e324073d83bc17b191d7e3f" +checksum = "66d4c8b64f049c6721ec8ccec37ddfc3d641c4a7fca57e8f2a89de509c73df39" dependencies = [ "libc", "rtoolbox", - "windows-sys 0.48.0", + "windows-sys 0.59.0", ] [[package]] @@ -3701,12 +3890,12 @@ dependencies = [ [[package]] name = "rtoolbox" -version = "0.0.2" +version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c247d24e63230cdb56463ae328478bd5eac8b8faa8c69461a77e8e323afac90e" +checksum = "a7cc970b249fbe527d6e02e0a227762c9108b2f49d81094fe357ffc6d14d7f6f" dependencies = [ "libc", - "windows-sys 0.48.0", + "windows-sys 0.52.0", ] [[package]] @@ -3718,6 +3907,40 @@ dependencies = [ "tinyvec", ] +[[package]] +name = "rust-embed" +version = "8.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e5fbc0ee50fcb99af7cebb442e5df7b5b45e9460ffa3f8f549cd26b862bec49d" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bf418c9a2e3f6663ca38b8a7134cc2c2167c9d69688860e8961e3faa731702e" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "08d55b95147fe01265d06b3955db798bdaed52e60e2211c41137701b3aba8e21" +dependencies = [ + "sha2", + "walkdir", +] + [[package]] name = "rustc-demangle" version = "0.1.24" @@ -3760,14 +3983,14 @@ dependencies = [ [[package]] name = "rustix" -version = "1.0.3" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e56a18552996ac8d29ecc3b190b4fdbb2d91ca4ec396de7bbffaf43f3d637e96" +checksum = "d97817398dd4bb2e6da002002db259209759911da105da92bec29ccb12cf58bf" dependencies = [ "bitflags 2.9.0", "errno", "libc", - "linux-raw-sys 0.9.3", + "linux-raw-sys 0.9.4", "windows-sys 0.59.0", ] @@ -3785,14 +4008,14 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.25" +version = "0.23.26" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "822ee9188ac4ec04a2f0531e55d035fb2de73f18b41a63c70c2712503b6fb13c" +checksum = "df51b5869f3a441595eac5e8ff14d486ff285f7b8c0df8770e49c3b56351f0f0" dependencies = [ "once_cell", "ring", "rustls-pki-types", - "rustls-webpki 0.103.0", + "rustls-webpki 0.103.1", "subtle", "zeroize", ] @@ -3848,9 +4071,9 @@ dependencies = [ [[package]] name = "rustls-webpki" -version = "0.103.0" +version = "0.103.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0aa4eeac2588ffff23e9d7a7e9b3f971c5fb5b7ebc9452745e0c232c64f83b2f" +checksum = "fef8b8769aaccf73098557a87cd1816b4f9c7c16811c9c77142aa695c16f2c03" dependencies = [ "ring", "rustls-pki-types", @@ -3921,6 +4144,15 @@ dependencies = [ "cipher", ] +[[package]] +name = "same-file" +version = "1.0.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502" +dependencies = [ + "winapi-util", +] + [[package]] name = "schannel" version = "0.1.27" @@ -3969,6 +4201,21 @@ dependencies = [ "libc", ] +[[package]] +name = "self_cell" +version = "0.10.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e14e4d63b804dc0c7ec4a1e52bcb63f02c7ac94476755aa579edac21e01f915d" +dependencies = [ + "self_cell 1.2.0", +] + +[[package]] +name = "self_cell" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f7d95a54511e0c7be3f51e8867aa8cf35148d7b9445d44de2f943e2b206e749" + [[package]] name = "semver" version = "1.0.26" @@ -4058,7 +4305,7 @@ dependencies = [ "chrono", "hex", "indexmap 1.9.3", - "indexmap 2.8.0", + "indexmap 2.9.0", "serde", "serde_derive", "serde_json", @@ -4111,9 +4358,9 @@ dependencies = [ [[package]] name = "shellexpand" -version = "3.1.0" +version = "3.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" +checksum = "8b1fdf65dd6331831494dd616b30351c38e96e45921a27745cf98490458b90bb" dependencies = [ "dirs", ] @@ -4147,9 +4394,9 @@ dependencies = [ [[package]] name = "signal-hook-registry" -version = "1.4.2" +version = "1.4.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a9e9e0b4211b72e7b8b6e85c807d36c212bdb33ea8587f7569562a84df5465b1" +checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" dependencies = [ "libc", ] @@ -4191,20 +4438,29 @@ dependencies = [ "autocfg", ] +[[package]] +name = "slugify" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d6b8cf203d2088b831d7558f8e5151bfa420c57a34240b28cee29d0ae5f2ac8b" +dependencies = [ + "unidecode", +] + [[package]] name = "smallvec" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fcf8323ef1faaee30a44a340193b1ac6814fd9b7b4e88e9d4519a3e4abe1cfd" +checksum = "8917285742e9f3e1683f0a9c4e6b57960b7314d0b08d30d1ecd426713ee2eee9" dependencies = [ "serde", ] [[package]] name = "socket2" -version = "0.5.8" +version = "0.5.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c970269d99b64e60ec3bd6ad27270092a5394c4e309314b18ae3fe575695fbe8" +checksum = "4f5fd57c80058a56cf5c777ab8a126398ece8e442983605d280a44ce79d0edef" dependencies = [ "libc", "windows-sys 0.52.0", @@ -4241,9 +4497,9 @@ dependencies = [ [[package]] name = "sqlx" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4410e73b3c0d8442c5f99b425d7a435b5ee0ae4167b3196771dd3f7a01be745f" +checksum = "f3c3a85280daca669cfd3bcb68a337882a8bc57ec882f72c5d13a430613a738e" dependencies = [ "sqlx-core", "sqlx-macros", @@ -4254,10 +4510,11 @@ dependencies = [ [[package]] name = "sqlx-core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a007b6936676aa9ab40207cde35daab0a04b823be8ae004368c0793b96a61e0" +checksum = "f743f2a3cea30a58cd479013f75550e879009e3a02f616f18ca699335aa248c3" dependencies = [ + "base64 0.22.1", "bytes", "crc", "crossbeam-queue", @@ -4269,13 +4526,12 @@ dependencies = [ "futures-util", "hashbrown 0.15.2", "hashlink", - "indexmap 2.8.0", + "indexmap 2.9.0", "log", "memchr", "once_cell", "percent-encoding", - "rustls 0.23.25", - "rustls-pemfile 2.2.0", + "rustls 0.23.26", "serde", "serde_json", "sha2", @@ -4292,9 +4548,9 @@ dependencies = [ [[package]] name = "sqlx-macros" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3112e2ad78643fef903618d78cf0aec1cb3134b019730edb039b69eaf531f310" +checksum = "7f4200e0fde19834956d4252347c12a083bdcb237d7a1a1446bffd8768417dce" dependencies = [ "proc-macro2", "quote", @@ -4305,9 +4561,9 @@ dependencies = [ [[package]] name = "sqlx-macros-core" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e9f90acc5ab146a99bf5061a7eb4976b573f560bc898ef3bf8435448dd5e7ad" +checksum = "882ceaa29cade31beca7129b6beeb05737f44f82dbe2a9806ecea5a7093d00b7" dependencies = [ "dotenvy", "either", @@ -4331,9 +4587,9 @@ dependencies = [ [[package]] name = "sqlx-mysql" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4560278f0e00ce64938540546f59f590d60beee33fffbd3b9cd47851e5fff233" +checksum = "0afdd3aa7a629683c2d750c2df343025545087081ab5942593a5288855b1b7a7" dependencies = [ "atoi", "base64 0.22.1", @@ -4375,9 +4631,9 @@ dependencies = [ [[package]] name = "sqlx-postgres" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5b98a57f363ed6764d5b3a12bfedf62f07aa16e1856a7ddc2a0bb190a959613" +checksum = "a0bedbe1bbb5e2615ef347a5e9d8cd7680fb63e77d9dafc0f29be15e53f1ebe6" dependencies = [ "atoi", "base64 0.22.1", @@ -4414,9 +4670,9 @@ dependencies = [ [[package]] name = "sqlx-sqlite" -version = "0.8.3" +version = "0.8.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f85ca71d3a5b24e64e1d08dd8fe36c6c95c339a896cc33068148906784620540" +checksum = "c26083e9a520e8eb87a06b12347679b142dc2ea29e6e409f805644a7a979a5bc" dependencies = [ "atoi", "flume", @@ -4432,6 +4688,7 @@ dependencies = [ "serde", "serde_urlencoded", "sqlx-core", + "thiserror 2.0.12", "time", "tracing", "url", @@ -4532,6 +4789,15 @@ dependencies = [ "syn", ] +[[package]] +name = "sys-locale" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8eab9a99a024a169fe8a903cf9d4a3b3601109bcc13bd9e3c6fff259138626c4" +dependencies = [ + "libc", +] + [[package]] name = "sysinfo" version = "0.30.13" @@ -4570,14 +4836,14 @@ dependencies = [ [[package]] name = "tempfile" -version = "3.19.0" +version = "3.19.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "488960f40a3fd53d72c2a29a58722561dee8afdd175bd88e3db4677d7b2ba600" +checksum = "7437ac7763b9b123ccf33c338a5cc1bac6f69b45a136c19bdd8a65e3916435bf" dependencies = [ "fastrand", "getrandom 0.3.2", "once_cell", - "rustix 1.0.3", + "rustix 1.0.5", "windows-sys 0.59.0", ] @@ -4587,7 +4853,7 @@ version = "0.4.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "45c6481c4829e4cc63825e62c49186a34538b7b2750b73b266581ffb612fb5ed" dependencies = [ - "rustix 1.0.3", + "rustix 1.0.5", "windows-sys 0.59.0", ] @@ -4663,9 +4929,9 @@ dependencies = [ [[package]] name = "time" -version = "0.3.40" +version = "0.3.41" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9d9c75b47bdff86fa3334a3db91356b8d7d86a9b839dab7d0bdc5c3d3a077618" +checksum = "8a7619e19bc266e0f9c5e6686659d394bc57973859340060a69221e57dbc0c40" dependencies = [ "deranged", "itoa", @@ -4686,9 +4952,9 @@ checksum = "c9e9a38711f559d9e3ce1cdb06dd7c5b8ea546bc90052da6d06bb76da74bb07c" [[package]] name = "time-macros" -version = "0.2.21" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "29aa485584182073ed57fd5004aa09c371f021325014694e432313345865fd04" +checksum = "3526739392ec93fd8b359c8e98514cb3e8e021beb4e5f597b00a0221f8ed8a49" dependencies = [ "num-conv", "time-core", @@ -4783,7 +5049,7 @@ version = "0.26.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b" dependencies = [ - "rustls 0.23.25", + "rustls 0.23.26", "tokio", ] @@ -4811,6 +5077,15 @@ dependencies = [ "tokio", ] +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + [[package]] name = "toml" version = "0.8.20" @@ -4838,7 +5113,7 @@ version = "0.22.24" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "17b4795ff5edd201c7cd6dca065ae59972ce77d1b80fa0a84d94950ece7d1474" dependencies = [ - "indexmap 2.8.0", + "indexmap 2.9.0", "serde", "serde_spanned", "toml_datetime", @@ -4856,7 +5131,7 @@ dependencies = [ "axum", "base64 0.22.1", "bytes", - "h2 0.4.8", + "h2 0.4.9", "http 1.3.1", "http-body 1.0.1", "http-body-util", @@ -4964,6 +5239,15 @@ version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8df9b6e13f2d32c91b9bd719c00d1958837bc7dec474d94952798cc8e69eeec3" +[[package]] +name = "tr" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a592877f7cb2e5a6327b8c908fa6d51098482b1c87d478abdd783e61218f8151" +dependencies = [ + "lazy_static", +] + [[package]] name = "tracing" version = "0.1.41" @@ -5057,6 +5341,15 @@ version = "0.2.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" +[[package]] +name = "type-map" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f" +dependencies = [ + "rustc-hash 1.1.0", +] + [[package]] name = "typed-builder" version = "0.18.2" @@ -5083,6 +5376,25 @@ version = "1.18.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1dccffe3ce07af9386bfd29e80c0ab1a8205a2fc34e4bcd40364df902cfa8f3f" +[[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-bidi" version = "0.3.18" @@ -5139,6 +5451,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1fc81956842c57dac11422a97c3b8195a1ff727f06e85c84ed2e8aa277c9a0fd" +[[package]] +name = "unidecode" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "402bb19d8e03f1d1a7450e2bd613980869438e0666331be3e073089124aa1adc" + [[package]] name = "universal-hash" version = "0.5.1" @@ -5218,6 +5536,16 @@ version = "0.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b928f33d975fc6ad9f86c8f283853ad26bdd5b10b7f1542aa2fa15e2289105a" +[[package]] +name = "walkdir" +version = "2.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "29790946404f91d9c5d06f9874efddea1dc06c5efe94541a7d6863108e3a5e4b" +dependencies = [ + "same-file", + "winapi-util", +] + [[package]] name = "want" version = "0.3.1" @@ -5346,9 +5674,9 @@ dependencies = [ [[package]] name = "wayland-protocols" -version = "0.31.2" +version = "0.32.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8f81f365b8b4a97f422ac0e8737c438024b5951734506b0e1d775c73030561f4" +checksum = "0781cf46869b37e36928f7b432273c0995aa8aed9552c556fb18754420541efc" dependencies = [ "bitflags 2.9.0", "wayland-backend", @@ -5358,9 +5686,9 @@ dependencies = [ [[package]] name = "wayland-protocols-wlr" -version = "0.2.0" +version = "0.3.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad1f61b76b6c2d8742e10f9ba5c3737f6530b4c243132c2a2ccc8aa96fe25cd6" +checksum = "248a02e6f595aad796561fa82d25601bd2c8c3b145b1c7453fc8f94c1a58f8b2" dependencies = [ "bitflags 2.9.0", "wayland-backend", @@ -5426,9 +5754,9 @@ checksum = "53a85b86a771b1c87058196170769dd264f66c0782acf1ae6cc51bfd64b39082" [[package]] name = "whoami" -version = "1.5.2" +version = "1.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "372d5b87f58ec45c384ba03563b03544dc5fadc3983e434b286913f5b4a9bb6d" +checksum = "6994d13118ab492c3c80c1f81928718159254c53c472bf9ce36f8dae4add02a7" dependencies = [ "redox_syscall", "wasite", @@ -5451,6 +5779,15 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" +[[package]] +name = "winapi-util" +version = "0.1.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" +dependencies = [ + "windows-sys 0.59.0", +] + [[package]] name = "winapi-x86_64-pc-windows-gnu" version = "0.4.0" @@ -5463,7 +5800,7 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e48a53791691ab099e5e2ad123536d0fff50652600abaf43bbf952894110d0be" dependencies = [ - "windows-core", + "windows-core 0.52.0", "windows-targets 0.52.6", ] @@ -5476,6 +5813,41 @@ dependencies = [ "windows-targets 0.52.6", ] +[[package]] +name = "windows-core" +version = "0.61.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4763c1de310c86d75a878046489e2e5ba02c649d185f21c67d4cf8a56d098980" +dependencies = [ + "windows-implement", + "windows-interface", + "windows-link", + "windows-result", + "windows-strings 0.4.0", +] + +[[package]] +name = "windows-implement" +version = "0.60.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a47fddd13af08290e67f4acabf4b459f647552718f683a7b415d290ac744a836" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "windows-interface" +version = "0.59.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bd9211b69f8dcdfa817bfd14bf1c97c9188afa36f4750130fcdf3f400eca9fa8" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "windows-link" version = "0.1.1" @@ -5489,7 +5861,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4286ad90ddb45071efd1a66dfa43eb02dd0dfbae1545ad6cc3c51cf34d7e8ba3" dependencies = [ "windows-result", - "windows-strings", + "windows-strings 0.3.1", "windows-targets 0.53.0", ] @@ -5511,6 +5883,15 @@ dependencies = [ "windows-link", ] +[[package]] +name = "windows-strings" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7a2ba9642430ee452d5a7aa78d72907ebe8cfda358e8cb7918a2050581322f97" +dependencies = [ + "windows-link", +] + [[package]] name = "windows-sys" version = "0.48.0" @@ -5725,9 +6106,9 @@ checksum = "271414315aff87387382ec3d271b52d7ae78726f5d44ac98b4f4030c91880486" [[package]] name = "winnow" -version = "0.7.4" +version = "0.7.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97b544156e9bebe1a0ffbc03484fc1ffe3100cbce3ffb17eac35f7cdd7ab36" +checksum = "63d3fcd9bba44b03821e7d699eeee959f3126dcc4aa8e4ae18ec617c2a5cea10" dependencies = [ "memchr", ] @@ -5753,17 +6134,16 @@ dependencies = [ [[package]] name = "wl-clipboard-rs" -version = "0.8.1" +version = "0.9.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12b41773911497b18ca8553c3daaf8ec9fe9819caf93d451d3055f69de028adb" +checksum = "8e5ff8d0e60065f549fafd9d6cb626203ea64a798186c80d8e7df4f8af56baeb" dependencies = [ - "derive-new", "libc", "log", - "nix", "os_pipe", + "rustix 0.38.44", "tempfile", - "thiserror 1.0.69", + "thiserror 2.0.12", "tree_magic_mini", "wayland-backend", "wayland-client", @@ -5841,11 +6221,11 @@ dependencies = [ [[package]] name = "zerocopy" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd97444d05a4328b90e75e503a34bad781f14e28a823ad3557f0750df1ebcbc6" +checksum = "2586fea28e186957ef732a5f8b3be2da217d65c5969d4b1e17f973ebbe876879" dependencies = [ - "zerocopy-derive 0.8.23", + "zerocopy-derive 0.8.24", ] [[package]] @@ -5861,9 +6241,9 @@ dependencies = [ [[package]] name = "zerocopy-derive" -version = "0.8.23" +version = "0.8.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6352c01d0edd5db859a63e2605f4ea3183ddbd15e2c4a9e7d32184df75e4f154" +checksum = "a996a8f63c5c4448cd959ac1bab0aaa3306ccfd060472f85943ee0750f0169be" dependencies = [ "proc-macro2", "quote", diff --git a/crates/atuin-client/Cargo.toml b/crates/atuin-client/Cargo.toml index cdeded3d6f2..2eae997d994 100644 --- a/crates/atuin-client/Cargo.toml +++ b/crates/atuin-client/Cargo.toml @@ -20,6 +20,7 @@ check-update = [] [dependencies] atuin-common = { path = "../atuin-common", version = "18.5.0" } +atuin-macro = { path = "../atuin-macro", version = "18.5.0" } log = { workspace = true } base64 = { workspace = true } diff --git a/crates/atuin-client/src/api_client.rs b/crates/atuin-client/src/api_client.rs index 0bd16c50b92..e09b0218589 100644 --- a/crates/atuin-client/src/api_client.rs +++ b/crates/atuin-client/src/api_client.rs @@ -325,12 +325,7 @@ impl<'a> Client<'a> { start: RecordIdx, count: u64, ) -> Result>> { - debug!( - "fetching record/s from host {}/{}/{}", - host.0.to_string(), - tag, - start - ); + debug!("fetching record/s from host {}/{}/{}", host.0, tag, start); let url = format!( "{}/api/v0/record/next?host={}&tag={}&count={}&start={}", diff --git a/crates/atuin-common/Cargo.toml b/crates/atuin-common/Cargo.toml index 2ca4aa676f3..e8fc75ec838 100644 --- a/crates/atuin-common/Cargo.toml +++ b/crates/atuin-common/Cargo.toml @@ -13,6 +13,8 @@ repository = { workspace = true } # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html [dependencies] +atuin-macro = { path = "../atuin-macro" } + time = { workspace = true } serde = { workspace = true } uuid = { workspace = true } @@ -25,8 +27,15 @@ directories = { workspace = true } sysinfo = "0.30.7" base64 = { workspace = true } getrandom = "0.2" +sys-locale = "0.3.2" lazy_static = "1.4.0" +i18n-embed = { version = "0.15.3", features = ["fluent", "fluent-system", "tr", "locale_config", "desktop-requester", "walkdir", "filesystem-assets"] } +rust-embed = "8" +i18n-embed-fl = "0.9.3" +slugify = "0.1.0" +paste = "1.0.15" +unic-langid = "0.9.5" [dev-dependencies] pretty_assertions = { workspace = true } diff --git a/crates/atuin-common/i18n.toml b/crates/atuin-common/i18n.toml new file mode 100644 index 00000000000..139d4dc613e --- /dev/null +++ b/crates/atuin-common/i18n.toml @@ -0,0 +1,13 @@ +# (Required) The language identifier of the language used in the +# source code for gettext system, and the primary fallback language +# (for which all strings must be present) when using the fluent +# system. +fallback_language = "en-GB" + +# Use the fluent localization system. +[fluent] +domain = "atuin" +# (Required) The path to the assets directory. +# The paths inside the assets directory should be structured like so: +# `assets_dir/{language}/{domain}.ftl` +assets_dir = "../../i18n" diff --git a/crates/atuin-common/src/i18n.rs b/crates/atuin-common/src/i18n.rs new file mode 100644 index 00000000000..b290138d508 --- /dev/null +++ b/crates/atuin-common/src/i18n.rs @@ -0,0 +1,42 @@ +use i18n_embed::{ + DesktopLanguageRequester, + fluent::{FluentLanguageLoader, fluent_language_loader}, +}; +pub use i18n_embed_fl::fl; +use rust_embed::RustEmbed; + +#[derive(RustEmbed)] +#[folder = "../../i18n"] // path to the compiled localization resources +struct Localizations; + +pub use atuin_macro::tl; +use lazy_static::lazy_static; + +lazy_static! { + // We assume that one LOADER is sufficient. Fluent provides more + // flexibility, but for now, this simplifies integration. + pub static ref LOADER: FluentLanguageLoader = { + // Load languages from central internationalization folder. + let language_loader: FluentLanguageLoader = fluent_language_loader!(); + let requested_languages = DesktopLanguageRequester::requested_languages(); + + let _result = i18n_embed::select( + &language_loader, &Localizations, &requested_languages); + language_loader + }; +} + +#[macro_export] +macro_rules! t { + // Case that t!("foo bar") is called with no runtime parameters to interpolate. + ($message_id:literal) => { + $crate::i18n::tl!($crate::i18n::fl, $crate::i18n::LOADER, $message_id) + }; + + // Case that t!("foo %{bar}", bar=baz.to_string()) is called with runtime parameters to interpolate. + ($message_id:literal, $($args:expr),*) => {{ + $crate::i18n::tl!($crate::i18n::fl, $crate::i18n::LOADER, $message_id, $($args), *) + }}; +} + +pub use t; diff --git a/crates/atuin-common/src/lib.rs b/crates/atuin-common/src/lib.rs index a776f09ab20..bf9a64afb50 100644 --- a/crates/atuin-common/src/lib.rs +++ b/crates/atuin-common/src/lib.rs @@ -54,6 +54,7 @@ macro_rules! new_uuid { } pub mod api; +pub mod i18n; pub mod record; pub mod shell; pub mod utils; diff --git a/crates/atuin-macro/Cargo.toml b/crates/atuin-macro/Cargo.toml new file mode 100644 index 00000000000..c0963af8389 --- /dev/null +++ b/crates/atuin-macro/Cargo.toml @@ -0,0 +1,41 @@ +[package] +name = "atuin-macro" +edition = "2021" +description = "macro library for atuin" + +rust-version = { workspace = true } +version = { workspace = true } +authors = { workspace = true } +license = { workspace = true } +homepage = { workspace = true } +repository = { workspace = true } + +[lib] +proc-macro = true + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +time = { workspace = true } +serde = { workspace = true } +uuid = { workspace = true } +typed-builder = { workspace = true } +eyre = { workspace = true } +sqlx = { workspace = true } +semver = { workspace = true } +thiserror = { workspace = true } +directories = { workspace = true } +sysinfo = "0.30.7" +base64 = { workspace = true } +getrandom = "0.2" +sys-locale = "0.3.2" + +lazy_static = "1.4.0" +i18n-embed = { version = "0.15.3", features = ["fluent", "fluent-system", "tr", "locale_config", "desktop-requester", "walkdir", "filesystem-assets"] } +rust-embed = "8" +i18n-embed-fl = "0.9.3" +slugify = "0.1.0" +paste = "1.0.15" +syn = "2.0.96" +quote = "1.0.38" +proc-macro2 = "1.0.93" diff --git a/crates/atuin-macro/i18n.toml b/crates/atuin-macro/i18n.toml new file mode 100644 index 00000000000..dbf00a52c7a --- /dev/null +++ b/crates/atuin-macro/i18n.toml @@ -0,0 +1,13 @@ +# (Required) The language identifier of the language used in the +# source code for gettext system, and the primary fallback language +# (for which all strings must be present) when using the fluent +# system. +fallback_language = "en-GB" + +# Use the fluent localization system. +[fluent] +domain = "atuin" +# (Required) The path to the assets directory. +# The paths inside the assets directory should be structured like so: +# `assets_dir/{language}/{domain}.ftl` +assets_dir = "./tests/i18n" diff --git a/crates/atuin-macro/src/lib.rs b/crates/atuin-macro/src/lib.rs new file mode 100644 index 00000000000..34393008cf1 --- /dev/null +++ b/crates/atuin-macro/src/lib.rs @@ -0,0 +1,76 @@ +#![forbid(unsafe_code)] +extern crate proc_macro; + +use proc_macro::TokenStream; +use proc_macro2::TokenStream as TokenStream2; +use quote::quote; +use slugify::slugify; +use syn::parse::Parser; + +fn literal_to_slug(literal: &syn::ExprLit) -> TokenStream2 { + // We pull out the actual text from the literal string expression. + let quoted: String = match &literal.lit { + syn::Lit::Str(message_id) => message_id.value(), + _ => panic!("Message ID must be a literal string"), + }; + // ...and pass it to slugify, + let slug = slugify!(quoted.as_str()); + // ...then turn it back into a literal string. + quote!(#slug) +} + +#[proc_macro] +pub fn tl(tokens: TokenStream) -> TokenStream { + // Begin by getting the individual arguments to tl! + let args = syn::punctuated::Punctuated::::parse_terminated + .parse(tokens) + .unwrap(); + + let mut arg_iter = args.iter(); + + // The first should always be the fl! macro for fluent (cf. atuin-common/src/i18n.rs) + let fl = arg_iter.next().unwrap(); + // atuin-common will send the universal loader as the second argument. This avoids + // every translation string having to explicitly pass it. + let loader = arg_iter.next().unwrap(); + + // The third argument should be the message ID. This logic takes the human-readable + // string and slugifies it. One of the main benefits of Fluent is that English-language + // ASCII is not the de facto reference (and things like gender and plurality can be + // encoded even where English makes no grammatical distinction). However, this approach + // still allows the `fl!` macro to be used directly, but saves having to switch all + // strings to slugs throughout the codebase just to make them translatable at all. + + // It is possible that the string literal representing the message (e.g. "Danger, Bill Bobinson") + // appears wrapped in a group or not, so we handle both possibilities. + // We use literal_to_slug to turn it to a slug, e.g. "danger-bill-bobinson" + let message_id: proc_macro2::TokenStream = match arg_iter.next() { + Some(syn::Expr::Group(arg)) => match *arg.expr.clone() { + syn::Expr::Lit(arg) => literal_to_slug(&arg), + arg => panic!("Message ID {:?} must be a literal", arg), + }, + Some(syn::Expr::Lit(arg)) => literal_to_slug(arg), + arg => panic!("Message ID {:?} must be a literal", arg), + }; + + // Reconstruct the arguments that we initially had, and pull in any extra ones + // that should go right through to Fluent. For example: + // t!("Danger ${name}", name="Bill Bobinson") + // -> tr!(fl, LOADER, "Danger ${name}", name="Bill Bobinson") + // -> fl!(LOADER, "danger-name", name="Bill Bobinson") + // `danger-name` is then searched for in the i18n/ folder, and should map + // to a template like `Danger, { $name }` that Fluent can insert the parameter into. + let args: Vec<_> = arg_iter.collect(); + + // If there are no parameters, then Fluent can do this entirely statically. + // Otherwise, it will require runtime interpolation. + if args.is_empty() { + TokenStream::from(quote!( + #fl!(#loader, #message_id) + )) + } else { + TokenStream::from(quote!( + #fl!(#loader, #message_id, #(#args),*) + )) + } +} diff --git a/crates/atuin-macro/tests/basic.rs b/crates/atuin-macro/tests/basic.rs new file mode 100644 index 00000000000..94b2193330f --- /dev/null +++ b/crates/atuin-macro/tests/basic.rs @@ -0,0 +1,123 @@ +use i18n_embed::fluent::{fluent_language_loader, FluentLanguageLoader}; +pub use i18n_embed_fl::fl; +use lazy_static::lazy_static; +use rust_embed::RustEmbed; + +#[derive(RustEmbed)] +#[folder = "tests/i18n"] // path to the compiled localization resources +struct Localizations; + +pub use atuin_macro::tl; + +lazy_static! { + // We assume that one LOADER is sufficient. Fluent provides more + // flexibility, but for now, this simplifies integration. + pub static ref LOADER: FluentLanguageLoader = { + // Load languages from central internationalization folder. + let language_loader: FluentLanguageLoader = fluent_language_loader!(); + let requested_languages = vec!["en-GB".parse().unwrap()]; + + let _result = i18n_embed::select( + &language_loader, &Localizations, &requested_languages); + language_loader + }; +} + +#[test] +fn basic_tl_without_parameter() { + assert_eq!( + tl!(fl, LOADER, "Danger, Bill Bobinson"), + "Danger, William of Bobinson" + ); +} + +#[test] +fn basic_tl_with_parameter() { + assert_eq!( + tl!( + fl, + LOADER, + "unrecognized subcommand '%{subcommand}'", + subcommand = "SUB" + ), + "unrecognised subcommand '\u{2068}SUB\u{2069}'" + ); +} + +#[test] +fn tl_with_non_en_range_without_parameter() { + let language_loader: FluentLanguageLoader = fluent_language_loader!(); + let requested_languages = vec!["ga-IE".parse().unwrap()]; + + let _result = i18n_embed::select(&language_loader, &Localizations, &requested_languages); + + assert_eq!( + tl!(fl, language_loader, "Danger, Bill Bobinson"), + "Contúirt, a Uilliam Mac Bhoboin" + ); +} + +#[test] +fn tl_with_non_en_range_with_parameter() { + let language_loader: FluentLanguageLoader = fluent_language_loader!(); + let requested_languages = vec!["hi-IN".parse().unwrap()]; + + let _result = i18n_embed::select(&language_loader, &Localizations, &requested_languages); + + assert_eq!( + tl!( + fl, + language_loader, + "Hello, my name is %{name}", + name = "रीमा" + ), + "नमस्ते, मेरा नाम \u{2068}रीमा\u{2069} है।" + ); +} + +#[test] +fn tl_with_selector_parameter() { + let language_loader: FluentLanguageLoader = fluent_language_loader!(); + + let _result = i18n_embed::select( + &language_loader, + &Localizations, + &vec!["en-GB".parse().unwrap()], + ); + + assert_eq!( + tl!(fl, language_loader, "the user that has files", gender = "f"), + "the user that has files" + ); + + assert_eq!( + tl!(fl, language_loader, "the user that has files", gender = "m"), + "the user that has files" + ); + + assert_eq!( + tl!(fl, language_loader, "the user that has files", gender = "o"), + "the user that has files" + ); + + let _result = i18n_embed::select( + &language_loader, + &Localizations, + &vec!["ga-IE".parse().unwrap()], + ); + + assert_eq!( + tl!(fl, language_loader, "the user that has files", gender = "f"), + "an t-úsáideoir a bhfuil comhaid aici" + ); + + assert_eq!( + tl!(fl, language_loader, "the user that has files", gender = "m"), + "an t-úsáideoir a bhfuil comhaid aige" + ); + + assert_eq!( + tl!(fl, language_loader, "the user that has files", gender = "o"), + "an t-úsáideoir a bhfuil comhaid acu" + ); +} diff --git a/crates/atuin-macro/tests/i18n/en-GB/atuin.ftl b/crates/atuin-macro/tests/i18n/en-GB/atuin.ftl new file mode 100644 index 00000000000..189d8f368d4 --- /dev/null +++ b/crates/atuin-macro/tests/i18n/en-GB/atuin.ftl @@ -0,0 +1,10 @@ +unrecognized-subcommand-subcommand = + unrecognised subcommand '{ $subcommand }' +danger-bill-bobinson = + Danger, William of Bobinson +hello-my-name-is-name = + Hello, my name is { $name } +the-user-that-has-files = + { $gender -> + *[other] the user that has files + } diff --git a/crates/atuin-macro/tests/i18n/ga-IE/atuin.ftl b/crates/atuin-macro/tests/i18n/ga-IE/atuin.ftl new file mode 100644 index 00000000000..8299d15f8a1 --- /dev/null +++ b/crates/atuin-macro/tests/i18n/ga-IE/atuin.ftl @@ -0,0 +1,8 @@ +danger-bill-bobinson = + Contúirt, a Uilliam Mac Bhoboin +the-user-that-has-files = + { $gender -> + [f] an t-úsáideoir a bhfuil comhaid aici + [m] an t-úsáideoir a bhfuil comhaid aige + *[other] an t-úsáideoir a bhfuil comhaid acu + } diff --git a/crates/atuin-macro/tests/i18n/hi-IN/atuin.ftl b/crates/atuin-macro/tests/i18n/hi-IN/atuin.ftl new file mode 100644 index 00000000000..d1a14928aa2 --- /dev/null +++ b/crates/atuin-macro/tests/i18n/hi-IN/atuin.ftl @@ -0,0 +1,2 @@ +hello-my-name-is-name = + नमस्ते, मेरा नाम { $name } है। diff --git a/crates/atuin/Cargo.toml b/crates/atuin/Cargo.toml index a31d3df7bed..5e6be42ed39 100644 --- a/crates/atuin/Cargo.toml +++ b/crates/atuin/Cargo.toml @@ -82,6 +82,9 @@ uuid = { workspace = true } sysinfo = "0.30.7" regex = "1.10.5" tempfile = { workspace = true } +i18n-embed = { version = "0.15.3", features = ["fluent", "fluent-system", "tr", "locale_config", "walkdir", "filesystem-assets"] } +rust-embed = "8" +i18n-embed-fl = "0.9.3" [target.'cfg(any(target_os = "windows", target_os = "macos"))'.dependencies] arboard = { version = "3.4", optional = true } diff --git a/crates/atuin/i18n.toml b/crates/atuin/i18n.toml new file mode 100644 index 00000000000..139d4dc613e --- /dev/null +++ b/crates/atuin/i18n.toml @@ -0,0 +1,13 @@ +# (Required) The language identifier of the language used in the +# source code for gettext system, and the primary fallback language +# (for which all strings must be present) when using the fluent +# system. +fallback_language = "en-GB" + +# Use the fluent localization system. +[fluent] +domain = "atuin" +# (Required) The path to the assets directory. +# The paths inside the assets directory should be structured like so: +# `assets_dir/{language}/{domain}.ftl` +assets_dir = "../../i18n" diff --git a/crates/atuin/src/command/external.rs b/crates/atuin/src/command/external.rs index 03deacbf3cb..609df580896 100644 --- a/crates/atuin/src/command/external.rs +++ b/crates/atuin/src/command/external.rs @@ -54,7 +54,11 @@ fn render_not_found(subcommand: &str, bin: &str) -> StyledStr { let _ = write!(output, "{error}error:{error:#} "); let _ = write!( output, - "unrecognized subcommand '{invalid}{subcommand}{invalid:#}' " + "{} ", + t!( + "unrecognized subcommand '%{subcommand}'", + subcommand = format!("{invalid}{subcommand}{invalid:#}") + ) ); let _ = write!( output, diff --git a/crates/atuin/src/main.rs b/crates/atuin/src/main.rs index eaa58664c40..ec943809b3e 100644 --- a/crates/atuin/src/main.rs +++ b/crates/atuin/src/main.rs @@ -1,5 +1,7 @@ #![warn(clippy::pedantic, clippy::nursery)] #![allow(clippy::use_self, clippy::missing_const_for_fn)] // not 100% reliable +#[macro_use] +extern crate atuin_common; use clap::Parser; use eyre::Result; diff --git a/i18n/en-GB/atuin.ftl b/i18n/en-GB/atuin.ftl new file mode 100644 index 00000000000..df8d0f09fb4 --- /dev/null +++ b/i18n/en-GB/atuin.ftl @@ -0,0 +1,2 @@ +unrecognized-subcommand-subcommand = + unrecognised subcommand '{ $subcommand }' diff --git a/i18n/en-US/atuin.ftl b/i18n/en-US/atuin.ftl new file mode 100644 index 00000000000..f57f1922653 --- /dev/null +++ b/i18n/en-US/atuin.ftl @@ -0,0 +1,2 @@ +unrecognized-subcommand-subcommand = + unrecognized subcommand '{ $subcommand }' diff --git a/i18n/ga-IE/atuin.ftl b/i18n/ga-IE/atuin.ftl new file mode 100644 index 00000000000..0c34b8c72b7 --- /dev/null +++ b/i18n/ga-IE/atuin.ftl @@ -0,0 +1,2 @@ +unrecognized-subcommand-subcommand = + ordú neamhaitheanta '{ $subcommand }'