diff --git a/.vscode/settings.json b/.vscode/settings.json index f2468ad8..4ac13f83 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -22,7 +22,8 @@ "image cache", "tilemap", "config", - "audio" + "audio", + "i18" ], "rust-analyzer.showUnlinkedFileNotification": false, "rust-analyzer.cargo.extraEnv": { diff --git a/Cargo.lock b/Cargo.lock index 5463b600..55c2b8c7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -185,9 +185,9 @@ dependencies = [ [[package]] name = "aho-corasick" -version = "1.0.4" +version = "1.1.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6748e8def348ed4d14996fa801f4122cd763fff530258cdc03f64b25f89d3a5a" +checksum = "ea5d730647d4fadd988536d06fecce94b7b4f2a7efdae548f1cf4b63205518ab" dependencies = [ "memchr", ] @@ -275,22 +275,27 @@ checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6" [[package]] name = "arboard" -version = "3.2.0" +version = "3.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6041616acea41d67c4a984709ddab1587fd0b10efe5cc563fee954d2f011854" +checksum = "ac57f2b058a76363e357c056e4f74f1945bf734d37b8b3ef49066c4787dde0fc" dependencies = [ "clipboard-win", "log", "objc", "objc-foundation", "objc_id", - "once_cell", "parking_lot", "thiserror", "winapi", "x11rb", ] +[[package]] +name = "arc-swap" +version = "1.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6" + [[package]] name = "arrayref" version = "0.3.7" @@ -435,13 +440,13 @@ dependencies = [ [[package]] name = "async-recursion" -version = "1.0.4" +version = "1.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0e97ce7de6cf12de5d7226c73f5ba9811622f4db3a5b91b55c53e987e5f91cba" +checksum = "5fd55a5ba1179988837d24ab4c7cc8ed6efdeff578ede0416b4225a5fca35bd0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -484,7 +489,7 @@ checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -579,9 +584,9 @@ checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" [[package]] name = "base64" -version = "0.21.2" +version = "0.21.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "604178f6c5c21f02dc555784810edfb88d34ac2c73b2eae109655649ee73ce3d" +checksum = "9ba43ea6f343b788c8764558649e08df62f86c6ef251fdaeb1ffd010a9ae50a2" [[package]] name = "bincode" @@ -594,11 +599,11 @@ dependencies = [ [[package]] name = "bindgen" -version = "0.64.0" +version = "0.68.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c4243e6031260db77ede97ad86c27e501d646a27ab57b59a574f725d98ab1fb4" +checksum = "726e4313eb6ec35d2730258ad4e15b547ee75d6afaa1361a922e78e59b7d8078" dependencies = [ - "bitflags 1.3.2", + "bitflags 2.4.0", "cexpr", "clang-sys", "lazy_static", @@ -609,7 +614,7 @@ dependencies = [ "regex", "rustc-hash", "shlex", - "syn 1.0.109", + "syn 2.0.37", ] [[package]] @@ -708,9 +713,9 @@ dependencies = [ [[package]] name = "bumpalo" -version = "3.13.0" +version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a3e2c3daef883ecc1b5d58c15adae93470a91d425f3532ba1695849656af3fc1" +checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" [[package]] name = "bytemuck" @@ -723,13 +728,13 @@ dependencies = [ [[package]] name = "bytemuck_derive" -version = "1.4.1" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fdde5c9cd29ebd706ce1b35600920a33550e402fc998a2e53ad3b42c3c47a192" +checksum = "965ab7eb5f8f97d2a083c799f3a1b994fc397b2fe2da5d1da1626ce15a39f2b1" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -746,15 +751,15 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38" [[package]] name = "bytes" -version = "1.4.0" +version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89b2fd2a0dcf38d7971e2194b6b6eebab45ae01067456a7fd93d5547a61b70be" +checksum = "a2bd12c1caf447e69cd4528f47f94d203fd2582878ecb9e9465484c4148a8223" [[package]] name = "cairo-sys-rs" -version = "0.18.0" +version = "0.18.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bd4d115132e01c0165e3bf5f56aedee8980b0b96ede4eb000b693c05a8adb8ff" +checksum = "685c9fa8e590b8b3d678873528d83411db17242a73fccaed827770ea0fedda51" dependencies = [ "libc", "system-deps", @@ -816,9 +821,9 @@ dependencies = [ [[package]] name = "cfg-expr" -version = "0.15.4" +version = "0.15.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b40ccee03b5175c18cde8f37e7d2a33bcef6f8ec8f7cc0d81090d1bb380949c9" +checksum = "03915af431787e6ffdcc74c645077518c6b6e01f80b761e0fbbfa288536311b3" dependencies = [ "smallvec", "target-lexicon", @@ -900,15 +905,14 @@ dependencies = [ [[package]] name = "cocoa-foundation" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "931d3837c286f56e3c58423ce4eba12d08db2374461a785c86f672b08b5650d6" +checksum = "8c6234cbb2e4c785b456c0644748b1ac416dd045799740356f8363dfe00c93f7" dependencies = [ "bitflags 1.3.2", "block", "core-foundation", "core-graphics-types", - "foreign-types", "libc", "objc", ] @@ -968,7 +972,7 @@ version = "4.6.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "35ed6e9d84f0b51a7f52daf1c7d71dd136fd7a3f41a8462b8cdb8c78d920fad4" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "memchr", ] @@ -1094,9 +1098,9 @@ dependencies = [ [[package]] name = "coreaudio-sys" -version = "0.2.12" +version = "0.2.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f034b2258e6c4ade2f73bf87b21047567fb913ee9550837c2316d139b0262b24" +checksum = "d8478e5bdad14dce236b9898ea002eabfa87cbe14f0aa538dbe3b6a4bec4332d" dependencies = [ "bindgen", ] @@ -1294,9 +1298,9 @@ dependencies = [ [[package]] name = "curl-sys" -version = "0.4.65+curl-8.2.1" +version = "0.4.66+curl-8.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "961ba061c9ef2fe34bbd12b807152d96f0badd2bebe7b90ce6c8c8b7572a0986" +checksum = "70c44a72e830f0e40ad90dda8a6ab6ed6314d39776599a58a2e5e37fbc6db5b9" dependencies = [ "cc", "libc", @@ -1305,7 +1309,7 @@ dependencies = [ "openssl-sys", "pkg-config", "vcpkg", - "winapi", + "windows-sys 0.48.0", ] [[package]] @@ -1321,9 +1325,9 @@ dependencies = [ [[package]] name = "dashmap" -version = "5.5.1" +version = "5.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "edd72493923899c6f10c641bdbdeddc7183d6396641d99c1a0d1597f37f92e28" +checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" dependencies = [ "cfg-if", "hashbrown 0.14.0", @@ -1439,6 +1443,17 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd0c93bb4b0c6d9b77f4435b0ae98c24d17f1c45b2ff844c6151a07256ca923b" +[[package]] +name = "displaydoc" +version = "0.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.37", +] + [[package]] name = "dlib" version = "0.5.2" @@ -1450,9 +1465,9 @@ dependencies = [ [[package]] name = "dlv-list" -version = "0.5.0" +version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d529fd73d344663edfd598ccb3f344e46034db51ebd103518eae34338248ad73" +checksum = "8aead04dc46b5f263c25721cf25c9e595951d15055f8063f92392fa0d7f64cf4" dependencies = [ "const-random", ] @@ -1560,7 +1575,7 @@ dependencies = [ "epaint", "log", "thiserror", - "type-map", + "type-map 0.5.0", "wgpu", "winit", ] @@ -1657,14 +1672,14 @@ dependencies = [ "heck", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] name = "enumflags2" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c041f5090df68b32bcd905365fd51769c8b9d553fe87fde0b683534f10c01bd2" +checksum = "5998b4f30320c9d93aed72f63af821bfdac50465b75428fce77b48ec482c3939" dependencies = [ "enumflags2_derive", "serde", @@ -1672,24 +1687,24 @@ dependencies = [ [[package]] name = "enumflags2_derive" -version = "0.7.7" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5e9a1f9f7d83e59740248a6e14ecf93929ade55027844dfcea78beafccc15745" +checksum = "f95e2801cd355d4a1a3e3953ce6ee5ae9603a5c833455343a8bfe3f44d418246" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] name = "enumn" -version = "0.1.11" +version = "0.1.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b893c4eb2dc092c811165f84dc7447fae16fb66521717968c34c509b39b1a5c5" +checksum = "c2ad8cef1d801a4686bfd8919f0b30eac4c8e48968c437a6405ded4fb5272d2b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -1718,9 +1733,9 @@ checksum = "5443807d6dff69373d433ab9ef5378ad8df50ca6298caf15de6e52e24aaf54d5" [[package]] name = "errno" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6b30f669a7961ef1631673d2766cc92f52d64f7ef354d4fe0ddfd30ed52f0f4f" +checksum = "136526188508e25c6fef639d7927dfb3e0e3084488bf202267829cf7fc23dbdd" dependencies = [ "errno-dragonfly", "libc", @@ -1755,12 +1770,12 @@ checksum = "0206175f82b8d6bf6652ff7d71a1e27fd2e4efde587fd368662814d6ec1d9ce0" [[package]] name = "exr" -version = "1.7.0" +version = "1.71.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d1e481eb11a482815d3e9d618db8c42a93207134662873809335a92327440c18" +checksum = "832a761f35ab3e6664babfbdc6cef35a4860e816ec3916dcfd0882954e98a8a8" dependencies = [ "bit_field", - "flume 0.10.14", + "flume 0.11.0", "half", "lebe", "miniz_oxide 0.7.1", @@ -1835,6 +1850,15 @@ dependencies = [ "windows-sys 0.48.0", ] +[[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 = "finl_unicode" version = "1.2.0" @@ -1863,6 +1887,50 @@ version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "98de4bbd547a563b716d8dfa9aad1cb19bfab00f4fa09a6a4ed21dbcf44ce9c4" +[[package]] +name = "fluent" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "61f69378194459db76abd2ce3952b790db103ceb003008d3d50d97c41ff847a7" +dependencies = [ + "fluent-bundle", + "unic-langid", +] + +[[package]] +name = "fluent-bundle" +version = "0.15.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e242c601dec9711505f6d5bbff5bedd4b61b2469f2e8bb8e57ee7c9747a87ffd" +dependencies = [ + "fluent-langneg", + "fluent-syntax", + "intl-memoizer", + "intl_pluralrules", + "rustc-hash", + "self_cell", + "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.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c0abed97648395c902868fee9026de96483933faa54ea3b40d652f7dfe61ca78" +dependencies = [ + "thiserror", +] + [[package]] name = "flume" version = "0.9.2" @@ -1876,14 +1944,10 @@ dependencies = [ [[package]] name = "flume" -version = "0.10.14" +version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1657b4441c3403d9f7b3409e47575237dac27b1b5726df654a6ecbf92f0f7577" +checksum = "55ac459de2512911e4b674ce33cf20befaba382d05b62b008afc1c8b57cbf181" dependencies = [ - "futures-core", - "futures-sink", - "nanorand", - "pin-project", "spin", ] @@ -1997,7 +2061,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -2098,10 +2162,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427" dependencies = [ "cfg-if", - "js-sys", "libc", "wasi 0.11.0+wasi-snapshot-preview1", - "wasm-bindgen", ] [[package]] @@ -2178,9 +2240,9 @@ dependencies = [ [[package]] name = "glam" -version = "0.24.1" +version = "0.24.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42218cb640844e3872cc3c153dc975229e080a6c4733b34709ef445610550226" +checksum = "b5418c17512bdf42730f9032c74e1ae39afc408745ebb2acf72fbc4691c17945" dependencies = [ "bytemuck", ] @@ -2423,9 +2485,9 @@ checksum = "95505c38b4572b2d910cecb0281560f54b440a19336cbbcb27bf6ce6adc6f5a8" [[package]] name = "hermit-abi" -version = "0.3.2" +version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "443144c8cdadd93ebf52ddb4056d257f5b52c04d3c804e657d19eb73fc33668b" +checksum = "d77f7ec81a6d05a3abb01ab6eb7590f6083d08449fe5a1c8b1e620283546ccb7" [[package]] name = "hex" @@ -2480,7 +2542,7 @@ version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bd6effc99afb63425aff9b05836f029929e345a6148a14b7ecd5ab67af944482" dependencies = [ - "bytes 1.4.0", + "bytes 1.5.0", "fnv", "itoa", ] @@ -2530,6 +2592,76 @@ dependencies = [ "libm", ] +[[package]] +name = "i18n-config" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0c9ce3c48cbc21fd5b22b9331f32b5b51f6ad85d969b99e793427332e76e7640" +dependencies = [ + "log", + "serde", + "serde_derive", + "thiserror", + "toml 0.8.0", + "unic-langid", +] + +[[package]] +name = "i18n-embed" +version = "0.14.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26261c73a1670a3f632a8765bb6b22c62fc391f3ddc805b87fd00cd6158e4456" +dependencies = [ + "arc-swap", + "fluent", + "fluent-langneg", + "fluent-syntax", + "i18n-embed-impl", + "intl-memoizer", + "lazy_static", + "locale_config", + "log", + "parking_lot", + "rust-embed", + "thiserror", + "unic-langid", + "walkdir", +] + +[[package]] +name = "i18n-embed-fl" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9fc1f8715195dffc4caddcf1cf3128da15fe5d8a137606ea8856c9300047d5a2" +dependencies = [ + "dashmap", + "find-crate", + "fluent", + "fluent-syntax", + "i18n-config", + "i18n-embed", + "lazy_static", + "proc-macro-error", + "proc-macro2", + "quote", + "strsim", + "syn 2.0.37", + "unic-langid", +] + +[[package]] +name = "i18n-embed-impl" +version = "0.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a2a4d5bff745c9a6e1459c490059281b353a4ab0a4e1e58b3eeeaef71f97d07b" +dependencies = [ + "find-crate", + "i18n-config", + "proc-macro2", + "quote", + "syn 2.0.37", +] + [[package]] name = "idna" version = "0.4.0" @@ -2648,6 +2780,25 @@ dependencies = [ "web-sys", ] +[[package]] +name = "intl-memoizer" +version = "0.5.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f" +dependencies = [ + "type-map 0.4.0", + "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 = "io-lifetimes" version = "1.0.11" @@ -2875,9 +3026,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.147" +version = "0.2.148" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4668fb0ea861c1df094127ac5f1da3409a82116a4ba74fca2e58ef927159bb3" +checksum = "9cdc71e17332e86d2e1d38c1f99edcb6288ee11b815fb1a4b049eaa2114d369b" [[package]] name = "libloading" @@ -2950,9 +3101,9 @@ checksum = "ef53942eb7bf7ff43a617b3e2c1c4a5ecf5944a7c1bc12d7ee39bbb15e5c1519" [[package]] name = "linux-raw-sys" -version = "0.4.5" +version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57bcfdad1b858c2db7c38303a6d2ad4dfaf5eb53dfeb0910128b2c26d6158503" +checksum = "1a9bad9f94746442c783ca431b22403b519cd7fbeed0533fdd6328b2f2212128" [[package]] name = "litrs" @@ -2960,6 +3111,32 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f9275e0933cf8bb20f008924c0cb07a0692fe54d8064996520bf998de9eb79aa" +[[package]] +name = "locale-codes" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d1f4cc9d2da40c19763d5dd398baf388f2cc1473ca3d53c578c75e9ad0402324" +dependencies = [ + "lazy_static", + "log", + "regex", + "serde", + "serde_json", +] + +[[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.10" @@ -3014,8 +3191,11 @@ dependencies = [ "futures", "git-version", "glam", + "i18n-embed", + "i18n-embed-fl", "image 0.24.7", "itertools", + "locale-codes", "luminol-term", "notify", "num_enum 0.7.0", @@ -3029,6 +3209,7 @@ dependencies = [ "rmxp-types", "rodio", "ron", + "rust-embed", "rust-ini", "rustysynth", "serde", @@ -3089,9 +3270,9 @@ dependencies = [ [[package]] name = "memchr" -version = "2.5.0" +version = "2.6.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d" +checksum = "8f232d6ef707e1956a43342693d2a31e72989554d58299d7a88738cc95b0d35c" [[package]] name = "memmap2" @@ -3169,7 +3350,7 @@ checksum = "49e7bc1560b95a3c4a25d03de42fe76ca718ab92d1a22a55b9b4cf67b3ae635c" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -3246,15 +3427,6 @@ dependencies = [ "unicode-xid", ] -[[package]] -name = "nanorand" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a51313c5820b0b02bd422f4b44776fbf47961755c74ce64afc73bfad10226c3" -dependencies = [ - "getrandom 0.2.10", -] - [[package]] name = "ndk" version = "0.7.0" @@ -3325,15 +3497,14 @@ dependencies = [ [[package]] name = "nix" -version = "0.26.2" +version = "0.26.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfdda3d196821d6af13126e40375cdf7da646a96114af134d5f417a9a1dc8e1a" +checksum = "598beaf3cc6fdd9a5dfb1630c2800c7acd31df7aaf0f565796fba2b53ca1af1b" dependencies = [ "bitflags 1.3.2", "cfg-if", "libc", "memoffset 0.7.1", - "static_assertions", ] [[package]] @@ -3422,16 +3593,6 @@ dependencies = [ "autocfg", ] -[[package]] -name = "num_cpus" -version = "1.16.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4161fcb6d602d4d2081af7c3a45852d875a03dd337a6bfdd6e06407b61342a43" -dependencies = [ - "hermit-abi", - "libc", -] - [[package]] name = "num_enum" version = "0.5.11" @@ -3480,7 +3641,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -3492,7 +3653,7 @@ dependencies = [ "proc-macro-crate", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -3562,9 +3723,9 @@ dependencies = [ [[package]] name = "object" -version = "0.32.0" +version = "0.32.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "77ac5bbd07aea88c60a577a1ce218075ffd59208b2d7ca97adf9bfc5aeb21ebe" +checksum = "9cf5f9dd3933bd50a9e1f149ec995f39ae2c496d31fd772c1fd45ebc27e902b0" dependencies = [ "memchr", ] @@ -3621,9 +3782,9 @@ checksum = "ff011a302c396a5197692431fc1948019154afc178baf7d8e37367442a4601cf" [[package]] name = "openssl-sys" -version = "0.9.91" +version = "0.9.93" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "866b5f16f90776b9bb8dc1e1802ac6f0513de3a7a7465867bfbc563dc737faac" +checksum = "db4d56a4c0478783083cfafcc42493dd4a981d41669da64b4572a2a089b51b1d" dependencies = [ "cc", "libc", @@ -3691,7 +3852,7 @@ dependencies = [ "proc-macro-error", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -3779,19 +3940,20 @@ checksum = "9b2a4787296e9989611394c33f193f676704af1686e70b8f8033ab5ba9a35a94" [[package]] name = "pest" -version = "2.7.2" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1acb4a4365a13f749a93f1a094a7805e5cfa0955373a9de860d962eaa3a5fe5a" +checksum = "d7a4d085fd991ac8d5b05a147b437791b4260b76326baf0fc60cf7c9c27ecd33" dependencies = [ + "memchr", "thiserror", "ucd-trie", ] [[package]] name = "pest_derive" -version = "2.7.2" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "666d00490d4ac815001da55838c500eafb0320019bbaa44444137c48b443a853" +checksum = "a2bee7be22ce7918f641a33f08e3f43388c7656772244e2bbb2477f44cc9021a" dependencies = [ "pest", "pest_generator", @@ -3799,22 +3961,22 @@ dependencies = [ [[package]] name = "pest_generator" -version = "2.7.2" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68ca01446f50dbda87c1786af8770d535423fa8a53aec03b8f4e3d7eb10e0929" +checksum = "d1511785c5e98d79a05e8a6bc34b4ac2168a0e3e92161862030ad84daa223141" dependencies = [ "pest", "pest_meta", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] name = "pest_meta" -version = "2.7.2" +version = "2.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "56af0a30af74d0445c0bf6d9d051c979b516a1a5af790d251daee76005420a48" +checksum = "b42f0394d3123e33353ca5e1e89092e533d2cc490389f2bd6131c43c634ebc5f" dependencies = [ "once_cell", "pest", @@ -3880,7 +4042,7 @@ dependencies = [ "phf_shared 0.11.2", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -3924,7 +4086,7 @@ checksum = "4359fd9c9171ec6e8c62926d6faaf553a8dc3f64e1507e76da7911b4f6a04405" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -3951,12 +4113,12 @@ version = "1.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bdc0001cfea3db57a2e24bc0d818e9e20e554b5f97fabb9bc231dc240269ae06" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "indexmap 1.9.3", "line-wrap", "quick-xml", "serde", - "time 0.3.27", + "time 0.3.29", ] [[package]] @@ -4049,7 +4211,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f4c021e1093a56626774e81216a4ce732a735e5bad4868a03f3ed65ca0c3919" dependencies = [ "once_cell", - "toml_edit", + "toml_edit 0.19.15", ] [[package]] @@ -4084,18 +4246,18 @@ checksum = "dc375e1527247fe1a97d8b7156678dfe7c1af2fc075c9a4db3690ecd2a148068" [[package]] name = "proc-macro2" -version = "1.0.66" +version = "1.0.67" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9" +checksum = "3d433d9f1a3e8c1263d9456598b16fec66f4acc9a74dacffd35c7bb09b3a1328" dependencies = [ "unicode-ident", ] [[package]] name = "profiling" -version = "1.0.9" +version = "1.0.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "46b2164ebdb1dfeec5e337be164292351e11daf63a05174c6776b2f47460f0c9" +checksum = "f89dff0959d98c9758c88826cc002e2c3d0b9dfac4139711d1f30de442f1139b" [[package]] name = "qoi" @@ -4209,9 +4371,9 @@ checksum = "f2ff9a1f06a88b01621b7ae906ef0211290d1c8a168a15542486a8f61c0833b9" [[package]] name = "rayon" -version = "1.7.0" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d2df5196e37bcc87abebc0053e20787d73847bb33134a69841207dd0a47f03b" +checksum = "9c27db03db7734835b3f53954b534c91069375ce6ccaa2e065441e07d9b6cdb1" dependencies = [ "either", "rayon-core", @@ -4219,14 +4381,12 @@ dependencies = [ [[package]] name = "rayon-core" -version = "1.11.0" +version = "1.12.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4b8f95bd6966f5c87776639160a66bd8ab9895d9d4ab01ddba9fc60661aebe8d" +checksum = "5ce3fb6ad83f861aac485e76e1985cd109d9a3713802152be56c3b1f0e0658ed" dependencies = [ - "crossbeam-channel", "crossbeam-deque", "crossbeam-utils", - "num_cpus", ] [[package]] @@ -4266,9 +4426,9 @@ dependencies = [ [[package]] name = "regex" -version = "1.9.3" +version = "1.9.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "81bc1d4caf89fac26a70747fe603c130093b53c773888797a6329091246d651a" +checksum = "697061221ea1b4a94a624f67d0ae2bfe4e22b8a17b6a192afb11046542cc8c47" dependencies = [ "aho-corasick", "memchr", @@ -4278,9 +4438,9 @@ dependencies = [ [[package]] name = "regex-automata" -version = "0.3.6" +version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fed1ceff11a1dddaee50c9dc8e4938bd106e9d89ae372f192311e7da498e3b69" +checksum = "c2f401f4955220693b56f8ec66ee9c78abffd8d1c4f23dc41a23839eb88f0795" dependencies = [ "aho-corasick", "memchr", @@ -4289,9 +4449,9 @@ dependencies = [ [[package]] name = "regex-syntax" -version = "0.7.4" +version = "0.7.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e5ea92a5b6195c6ef2a0295ea818b312502c6fc94dde986c5553242e18fd4ce2" +checksum = "dbb5fb1acd8a1a18b3dd5be62d25485eb770e05afb408a9627d14d451bae12da" [[package]] name = "renderdoc-sys" @@ -4382,7 +4542,7 @@ version = "0.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b91f7eff05f748767f183df4320a63d6936e9c6107d97c9e6bdd9784f4289c94" dependencies = [ - "base64 0.21.2", + "base64 0.21.4", "bitflags 2.4.0", "serde", "serde_derive", @@ -4397,6 +4557,40 @@ dependencies = [ "xmlparser", ] +[[package]] +name = "rust-embed" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b1e7d90385b59f0a6bf3d3b757f3ca4ece2048265d70db20a2016043d4509a40" +dependencies = [ + "rust-embed-impl", + "rust-embed-utils", + "walkdir", +] + +[[package]] +name = "rust-embed-impl" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3c3d8c6fd84090ae348e63a84336b112b5c3918b3bf0493a581f7bd8ee623c29" +dependencies = [ + "proc-macro2", + "quote", + "rust-embed-utils", + "syn 2.0.37", + "walkdir", +] + +[[package]] +name = "rust-embed-utils" +version = "8.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "873feff8cb7bf86fdf0a71bb21c95159f4e4a37dd7a4bd1855a940909b583ada" +dependencies = [ + "sha2 0.10.7", + "walkdir", +] + [[package]] name = "rust-ini" version = "0.19.0" @@ -4444,14 +4638,14 @@ dependencies = [ [[package]] name = "rustix" -version = "0.38.8" +version = "0.38.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19ed4fa021d81c8392ce04db050a3da9a60299050b7ae1cf482d862b54a7218f" +checksum = "747c788e9ce8e92b12cd485c49ddf90723550b654b32508f979b71a7b1ecda4f" dependencies = [ "bitflags 2.4.0", "errno", "libc", - "linux-raw-sys 0.4.5", + "linux-raw-sys 0.4.7", "windows-sys 0.48.0", ] @@ -4463,9 +4657,9 @@ checksum = "7ffc183a10b4478d04cbbbfc96d0873219d962dd5accaff2ffbd4ceb7df837f4" [[package]] name = "rustysynth" -version = "1.2.1" +version = "1.3.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b916492c4bdd1dba14c92761cc855f9ef12f3c7e4ef18cab07ee49e784c1c66b" +checksum = "a2316fb90175e4f747331f29c9275aaddf2868b355472e94a3b82ad235a719b5" [[package]] name = "ryu" @@ -4522,6 +4716,12 @@ dependencies = [ "tiny-skia", ] +[[package]] +name = "self_cell" +version = "0.10.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" + [[package]] name = "semver" version = "0.9.0" @@ -4557,29 +4757,29 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.187" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "30a7fe14252655bd1e578af19f5fa00fe02fd0013b100ca6b49fde31c41bae4c" +checksum = "cf9e0fcba69a370eed61bcf2b728575f726b50b55cba78064753d708ddc7549e" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.187" +version = "1.0.188" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e46b2a6ca578b3f1d4501b12f78ed4692006d79d82a1a7c561c12dbc3d625eb8" +checksum = "4eca7ac642d82aa35b60049a6eccb4be6be75e599bd2e9adb5f875a737654af2" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] name = "serde_json" -version = "1.0.105" +version = "1.0.107" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "693151e1ac27563d6dbcec9dee9fbd5da8539b20fa14ad3752b2e6d363ace360" +checksum = "6b420ce6e3d8bd882e9b243c6eed35dbc9a6110c9769e74b584e0d68d1f20c65" dependencies = [ "itoa", "ryu", @@ -4605,7 +4805,7 @@ checksum = "8725e1dfadb3a50f7e5ce0b1a540466f6ed3fe7a0fca2ac2b8b831d31316bd00" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -4682,9 +4882,9 @@ dependencies = [ [[package]] name = "sha1" -version = "0.10.5" +version = "0.10.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f04293dc80c3993519f2d7f6f511707ee7094fe0c6d3406feb330cdb3540eba3" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" dependencies = [ "cfg-if", "cpufeatures", @@ -4748,9 +4948,9 @@ checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" [[package]] name = "shlex" -version = "1.1.0" +version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43b2853a4d09f215c24cc5489c992ce46052d359b5109343cbafbf26bc62f8a3" +checksum = "a7cee0529a6d40f580e7a5e6c495c8fbfe21b7b52795ed4bb5e62cdf92bc6380" [[package]] name = "signal-hook" @@ -4834,15 +5034,15 @@ dependencies = [ [[package]] name = "smallvec" -version = "1.11.0" +version = "1.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "62bb4feee49fdd9f707ef802e22365a35de4b7b299de4763d44bfea899442ff9" +checksum = "942b4a808e05215192e39f4ab80813e599068285906cc91aa64f923db842bd5a" [[package]] name = "smithay-client-toolkit" -version = "0.16.0" +version = "0.16.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f307c47d32d2715eb2e0ece5589057820e0e5e70d07c247d1063e844e107f454" +checksum = "870427e30b8f2cbe64bf43ec4b86e88fe39b0a84b3f15efd9c9c2d020bc86eb9" dependencies = [ "bitflags 1.3.2", "calloop", @@ -5044,7 +5244,7 @@ dependencies = [ "proc-macro2", "quote", "rustversion", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -5148,9 +5348,9 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.29" +version = "2.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a" +checksum = "7303ef2c05cd654186cb250d29049a24840ca25d2747c25c0381c8d9e2f582e8" dependencies = [ "proc-macro2", "quote", @@ -5187,7 +5387,7 @@ dependencies = [ "cfg-expr", "heck", "pkg-config", - "toml 0.7.6", + "toml 0.7.8", "version-compare", ] @@ -5206,15 +5406,15 @@ dependencies = [ "cfg-if", "fastrand 2.0.0", "redox_syscall 0.3.5", - "rustix 0.38.8", + "rustix 0.38.14", "windows-sys 0.48.0", ] [[package]] name = "termcolor" -version = "1.2.0" +version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be55cf8942feac5c765c2c993422806843c9a9a45d4d5c407ad6dd2ea95eb9b6" +checksum = "6093bad37da69aab9d123a8091e4be0aa4a03e4d601ec641c327398315f62b64" dependencies = [ "winapi-util", ] @@ -5256,7 +5456,7 @@ version = "0.22.0" source = "git+https://github.com/wez/wezterm?rev=3666303c7b26c6c966b3f136dbb954686d334cc3#3666303c7b26c6c966b3f136dbb954686d334cc3" dependencies = [ "anyhow", - "base64 0.21.2", + "base64 0.21.4", "bitflags 1.3.2", "filedescriptor", "finl_unicode", @@ -5295,22 +5495,22 @@ dependencies = [ [[package]] name = "thiserror" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f" +checksum = "9d6d7a740b8a666a7e828dd00da9c0dc290dff53154ea77ac109281de90589b7" dependencies = [ "thiserror-impl", ] [[package]] name = "thiserror-impl" -version = "1.0.47" +version = "1.0.48" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b" +checksum = "49922ecae66cc8a249b77e68d1d0623c1b2c514f0060c27cdc68bd62a1219d35" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -5373,22 +5573,22 @@ dependencies = [ [[package]] name = "time" -version = "0.3.27" +version = "0.3.29" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0bb39ee79a6d8de55f48f2293a830e040392f1c5f16e336bdd1788cd0aadce07" +checksum = "426f806f4089c493dcac0d24c29c01e2c38baf8e30f1b716ee37e83d200b18fe" dependencies = [ "deranged", "itoa", "serde", "time-core", - "time-macros 0.2.13", + "time-macros 0.2.15", ] [[package]] name = "time-core" -version = "0.1.1" +version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7300fbefb4dadc1af235a9cef3737cea692a9d97e1b9cbcd4ebdae6f8868e6fb" +checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" [[package]] name = "time-macros" @@ -5402,9 +5602,9 @@ dependencies = [ [[package]] name = "time-macros" -version = "0.2.13" +version = "0.2.15" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "733d258752e9303d392b94b75230d07b0b9c489350c69b851fc6c065fde3e8f9" +checksum = "4ad70d68dba9e1f8aceda7aa6711965dfec1cac869f311a51bd08b3a2ccbce20" dependencies = [ "time-core", ] @@ -5456,6 +5656,15 @@ dependencies = [ "strict-num", ] +[[package]] +name = "tinystr" +version = "0.7.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b07bb54ef1f8ff27564b08b861144d3b8d40263efe07684f64987f4c0d044e3e" +dependencies = [ + "displaydoc", +] + [[package]] name = "tinyvec" version = "1.6.0" @@ -5482,14 +5691,26 @@ dependencies = [ [[package]] name = "toml" -version = "0.7.6" +version = "0.7.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c17e963a819c331dcacd7ab957d80bc2b9a9c1e71c804826d2f283dd65306542" +checksum = "dd79e69d3b627db300ff956027cc6c3798cef26d22526befdfcd12feeb6d2257" dependencies = [ "serde", "serde_spanned", "toml_datetime", - "toml_edit", + "toml_edit 0.19.15", +] + +[[package]] +name = "toml" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c226a7bba6d859b63c92c4b4fe69c5b6b72d0cb897dbc8e6012298e6154cb56e" +dependencies = [ + "serde", + "serde_spanned", + "toml_datetime", + "toml_edit 0.20.0", ] [[package]] @@ -5503,9 +5724,22 @@ dependencies = [ [[package]] name = "toml_edit" -version = "0.19.14" +version = "0.19.15" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b5bb770da30e5cbfde35a2d7b9b8a2c4b8ef89548a7a6aeab5c9a576e3e7421" +dependencies = [ + "indexmap 2.0.0", + "serde", + "serde_spanned", + "toml_datetime", + "winnow", +] + +[[package]] +name = "toml_edit" +version = "0.20.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8123f27e969974a3dfba720fdb560be359f57b44302d280ba72e76a74480e8a" +checksum = "8ff63e60a958cefbb518ae1fd6566af80d9d4be430a33f3723dfc47d1d411d95" dependencies = [ "indexmap 2.0.0", "serde", @@ -5535,7 +5769,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", ] [[package]] @@ -5595,9 +5829,18 @@ dependencies = [ [[package]] name = "ttf-parser" -version = "0.19.1" +version = "0.19.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a464a4b34948a5f67fddd2b823c62d9d92e44be75058b99939eae6c5b6960b33" +checksum = "49d64318d8311fc2668e48b63969f4343e0a85c4a109aa8460d6672e364b8bd1" + +[[package]] +name = "type-map" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b6d3364c5e96cb2ad1603037ab253ddd34d7fb72a58bdddf4b7350760fc69a46" +dependencies = [ + "rustc-hash", +] [[package]] name = "type-map" @@ -5610,9 +5853,9 @@ dependencies = [ [[package]] name = "typenum" -version = "1.16.0" +version = "1.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "497961ef93d974e23eb6f433eb5fe1b7930b659f06d12dec6fc44a8f554c0bba" +checksum = "42ff0bf0c66b8238c6f3b578df37d0b7848e55df8577b3f74f92a69acceeb825" [[package]] name = "ucd-trie" @@ -5630,6 +5873,25 @@ dependencies = [ "winapi", ] +[[package]] +name = "unic-langid" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "398f9ad7239db44fd0f80fe068d12ff22d78354080332a5077dc6f52f14dcf2f" +dependencies = [ + "unic-langid-impl", +] + +[[package]] +name = "unic-langid-impl" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e35bfd2f2b8796545b55d7d3fd3e89a0613f68a0d1c8bc28cb7ff96b411a35ff" +dependencies = [ + "serde", + "tinystr", +] + [[package]] name = "unicase" version = "2.7.0" @@ -5647,9 +5909,9 @@ checksum = "92888ba5573ff080736b3648696b70cafad7d250551175acbaa4e0385b3e1460" [[package]] name = "unicode-ident" -version = "1.0.11" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" [[package]] name = "unicode-normalization" @@ -5668,9 +5930,9 @@ checksum = "1dd624098567895118886609431a7c3b8f516e41d30e0643f03d94592a147e36" [[package]] name = "unicode-width" -version = "0.1.10" +version = "0.1.11" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c0edd1e5b14653f783770bce4a4dabb4a5108a5370a5f5d8cfe8710c361f6c8b" +checksum = "e51733f11c9c4f72aa0c160008246859e340b00807569a0da0e7a1079b27ba85" [[package]] name = "unicode-xid" @@ -5690,9 +5952,9 @@ dependencies = [ [[package]] name = "url" -version = "2.4.0" +version = "2.4.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "50bff7831e19200a85b17131d085c25d7811bc4e186efdaf54bbd132994a88cb" +checksum = "143b538f18257fac9cad154828a57c6bf5157e1aa604d4816b5995bf6de87ae5" dependencies = [ "form_urlencoded", "idna", @@ -5788,9 +6050,9 @@ checksum = "9d5b2c62b4012a3e1eca5a7e077d13b3bf498c4073e33ccd58626607748ceeca" [[package]] name = "walkdir" -version = "2.3.3" +version = "2.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698" +checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee" dependencies = [ "same-file", "winapi-util", @@ -5829,7 +6091,7 @@ dependencies = [ "once_cell", "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", "wasm-bindgen-shared", ] @@ -5863,7 +6125,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b" dependencies = [ "proc-macro2", "quote", - "syn 2.0.29", + "syn 2.0.37", "wasm-bindgen-backend", "wasm-bindgen-shared", ] @@ -6198,9 +6460,9 @@ checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" [[package]] name = "winapi-util" -version = "0.1.5" +version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178" +checksum = "f29e6f9198ba0d26b4c9f07dbe6f9ed633e1f3d5b8b414090084349e46a52596" dependencies = [ "winapi", ] @@ -6542,15 +6804,15 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2769203cd13a0c6015d515be729c526d041e9cf2c0cc478d57faee85f40c6dcd" dependencies = [ - "nix 0.26.2", + "nix 0.26.4", "winapi", ] [[package]] name = "xml-rs" -version = "0.8.16" +version = "0.8.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "47430998a7b5d499ccee752b41567bc3afc57e1327dc855b1a2aa44ce29b5fa1" +checksum = "0fcb9cbac069e033553e8bb871be2fbdffcab578eb25bd0f7c508cedc6dcd75a" [[package]] name = "xmlparser" @@ -6591,13 +6853,13 @@ dependencies = [ "futures-sink", "futures-util", "hex", - "nix 0.26.2", + "nix 0.26.4", "once_cell", "ordered-stream", "rand 0.8.5", "serde", "serde_repr", - "sha1 0.10.5", + "sha1 0.10.6", "static_assertions", "tracing", "uds_windows", diff --git a/Cargo.toml b/Cargo.toml index a4fec802..02a00356 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -97,10 +97,18 @@ luminol-term = { version = "*", path = "luminol-term" } steamworks = { version = "0.10.0", optional = true } crc = { version = "3.0", optional = true } +# Internationalization and Localization +i18n-embed = { version = "0.14.0", features = [ + "fluent-system", + "desktop-requester", +] } +i18n-embed-fl = "0.7.0" +locale-codes = "0.3.0" +rust-embed = "8.0.0" + [features] steamworks = ["dep:steamworks", "crc"] - [target.'cfg(windows)'.dependencies] windows = { version = "0.51.1", features = ["Win32_System_Registry"] } winreg = "0.51.0" diff --git a/i18n.toml b/i18n.toml new file mode 100644 index 00000000..04d478c2 --- /dev/null +++ b/i18n.toml @@ -0,0 +1,4 @@ +fallback_language = "en-AU" + +[fluent] +assets_dir = "lang" diff --git a/lang/en-AU/luminol.ftl b/lang/en-AU/luminol.ftl new file mode 100644 index 00000000..e29e617e --- /dev/null +++ b/lang/en-AU/luminol.ftl @@ -0,0 +1,239 @@ +# Copyright (C) 2023 Lily Lyons +# +# This file is part of Luminol. +# +# Luminol is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# Luminol is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with Luminol. If not, see . + +luminol = Luminol + +# General words +start = Start +unloaded = Unloaded +scale = Scale +events = Events +fog = Fog +new_project = New Project +open_project = Open Project +fullscreen = Fullscreen +maps = Maps +items = Items +common_event = Common Event +common_events = Common Events +scripts = Scripts +sound_test = Sound Test +about = About +ok = Ok +cancel = Cancel +apply = Apply +name = Name +icon = Icon +description = Description +scope = Scope +occasion = Occasion +search = Search +code = Code +type = Type +parameters = Parameters +save = Save +position = Position +variants = Variants +switch = Switch +variable = Variable +example_allcaps = EXAMPLE + +# Errors +fatal_error = Fatal Error +deadlock_detected_title = Deadlock #{$deadlockIndex} +deadlock_detected_description = Luminol has deadlocked! Please file an issue. + { $numOfDeadLocks } deadlocks detected +thread_id = Thread Id {$id} + +# Tabs +# > Started +tab_started_title_label = Get Started +tab_started_recent_projects_label = Recent +# > Map +tab_map_title_label = Map {$id}: {$name} +tab_map_layer_section_sv = Layer {$num} +tab_map_panorama_label = Panorama +tab_map_dva_cb = Display Visible Area +tab_map_pemr_cb = Preview event move routes +tab_map_cmrp_btn = Clear move route preview + +# Windows +# > About +window_about_title_label = About +window_about_luminol_label = About Luminol +window_about_version_text_label = Luminol version {$version} +window_about_description_text_label = Luminol is a FOSS version of the RPG Maker XP editor. +window_about_authors_label = Authors: + {$authorsArray} +# > Common Event Editor +window_common_events_editing_label = Editing Common Event {$name} +window_common_events_type_none_sv = None +window_common_events_type_autorun_sv = Autorun +window_common_events_type_parallel_sv = Parallel +# > Config +window_config_title_label = Local Luminol Config +window_config_proj_name_label = Project name +window_config_scripts_path_label = Scripts path +window_config_use_ron_cb = Use RON (Rusty Object Notation) +window_config_rgss_ver_label = RGSS Version +window_config_playtest_exe_btn = Playtest Executable +# > Event Editor +window_event_title_label = Event: {$name}, {$id} in Map {$map_id} +window_event_new_page_btn = New page +window_event_copy_page_btn = Copy page +window_event_paste_page_btn = Paste page +window_event_clear_page_btn = Clear page +window_event_tab_configuration_sv = Configuration +window_event_tab_graphic_sv = Graphic +window_event_tab_commands_sv = Commands +window_event_conf_condition_label = Condition +window_event_conf_switch_cb = Switch +window_event_conf_variable_cb = Variable +window_event_conf_or_above_label = or above +window_event_conf_self_switch_cb = Self Switch +window_event_conf_is_on_label = is on +window_event_conf_options_label = Options +window_event_conf_option_move_anim_cb = Move Animation +window_event_conf_option_stop_anim_cb = Stop Animation +window_event_conf_option_direction_fix_cb = Direction Fix +window_event_conf_option_through_cb = Through +window_event_conf_option_aot_cb = Always on Top +window_event_conf_trigger_label = Trigger +window_event_conf_trigger_action_btn_rv = Action Button +window_event_conf_trigger_player_touch_rv = Player Touch +window_event_conf_trigger_event_touch_rv = Event Touch +window_event_conf_trigger_autorun_rv = Autorun +window_event_conf_trigger_parallel_proc_rv = Parallel Process +window_event_graphic_add_image_btn = Add image +# > Graphic Picker +window_graphic_picker_title_label = Graphic Picker +# > Items +window_items_title_label = Editing item {$name} +window_items_change_max_btn = Change maximum... +window_items_user_anim_field = User Animation +window_items_target_anim_field = Target Animation +window_items_menu_se_field = Menu Use SE +window_items_msep_label = Menu Sound Effect Picker +# > Map Picker +window_map_picker_title_label = Map Picker +window_map_picker_root_label = root +# > Egui Inspection +window_egui_inspec_title_label = Egui Inspection +# > Egui Memory +window_egui_memory_title_label = Egui Memory +# > New Project +window_new_proj_my_proj_str = My Project +window_new_proj_name_label = Project Name +window_new_proj_with_git_cb = Initialize with git repository +window_new_proj_git_branch_label = Git Branch +window_new_proj_rgss_runtime_label = RGSS runtime +window_new_proj_with_exe_download_cb = Download latest version of {$variant} +window_new_proj_dl_and_unzipping_label = Downloading & Unzipping {$current}/{$total} +# > Script Editor +window_script_editor_fallback_title_label = Scripts +window_script_editor_title_label = Editing Script {$name} +window_script_editor_insert_btn = Insert +window_script_editor_delete_btn = Delete +window_script_editor_new_str = New Script +# > Sound +window_sound_test_title_label = Sound Test +window_sound_test_play_btn = Play +window_sound_test_stop_btn = Stop +window_sound_test_volume_label = Volume +window_sound_test_pitch_label = Pitch +# > Command Generator +window_commandgen_title_label = Luminol Command Maker +window_commandgen_desc_label = Description for this command +window_commandgen_lumi_label = Lumi help text +window_commandgen_lumi_onhover_label = This text will be shown by lumi if she's enabled +window_commandgen_contcode_label = Cont. Code +window_commandgen_contcode_onhover_label = Luminol will assume that any following commands with this code are a part of this one +window_commandgen_syntax_highlighting_cb = Enable Ruby syntax highlighting +window_commandgen_endcode_label = End Code +window_commandgen_endcode_onhover_label = Luminol will add this command to denote the end of the branch +window_commandgen_him_cb = Hide in menu +window_commandgen_preview_btn = Preview UI +window_commandgen_position_onhover_label = Position of this parameter, when not set it is assumed to be the index of the parameter +window_commandgen_grouped_params_label = Grouped parameters +window_commandgen_grouped_params_onhover_label = This parameter groups together other parameters +window_commandgen_subparams_label = Subparameters +window_commandgen_subparams_onhover_label = This parameter selects one of the following parameters +window_commandgen_description_onhover_label = Description for this parameter +window_commandgen_variants_onhover_label = Variants for the enum +window_commandgen_ui_example_label = [{$code}] {$name} UI Example +# > General +window_untitled_title = Untitled Window + +# Modals +# > Switch +modal_switch_title_label = Switch Picker +# > Variable +modal_variable_title_label = Variable Picker + +# Top Bar +# > File Menu +topbar_file_section = File +topbar_file_current_proj_label = Current project: + {$path} +topbar_file_no_proj_open_label = No project open +topbar_file_proj_config_btn = Project Config +topbar_file_close_proj_btn = Close Project +topbar_file_save_proj_btn = Save Project +topbar_file_command_maker_btn = Command Maker +topbar_file_quit_btn = Quit +# > Appearance Menu +topbar_appearance_section = Appearance +topbar_appearance_egui_conf_btn = Egui Settings +topbar_appearance_egui_catppuccin_section = Catppuccin theme +topbar_appearance_code_theme_section = Code Theme +topbar_appearance_code_sample_label = Code sample +topbar_appearance_clt_btn = Clear Loaded Textures +topbar_appearance_clt_onhover_label = You may need to reopen maps/windows for any changes to take effect. +# > Data Menu +topbar_data_section = Data +# > Help Menu +topbar_help_section = Help +topbar_egui_inspection_btn = Egui Inspection +topbar_egui_memory_btn = Egui Memory +topbar_debug_on_hover_tv = Debug on hover +# > Other UI Controls +topbar_playtest_btn = Playtest +topbar_terminal_btn = Terminal +topbar_brush_label = Brush +topbar_egui_settings_label = Egui Settings + +# Toast Notifications +toast_error_load_proj = Error loading the project: {$why} +toast_error_starting_game = Error starting game (tried steamshim.exe and then game.exe): {$why} +toast_error_starting_shell = Error starting shell: {$why} +toast_error_displaying_term = Error displaying terminal: {$why} +toast_error_cannot_load_icon = Could not load `{$icon_path}` icon: {$why} +toast_error_reading_icons = Error while reading `Graphics/Icons`: {$why} +toast_error_creating_proj = Failed to create the project: {$why} +toast_error_init_git = Error while initializing the git repository: {$why} +toast_error_downloading_rgss = Error downloading {$variant}: {$why} +toast_error_getting_body_resp = Error getting response body for {$variant}: {$why} +toast_error_read_zip = Failed to read the zip archive for {$variant}: {$why} +toast_error_invalid_file_path = Invalid file path {$file_path} +toast_error_create_dir = Failed to create directory {$file_path}: {$why} +toast_error_reading_file_data = Failed to read file data {$file_path}: {$why} +toast_error_saving_file_data = Failed to save file data {$file_path}: {$why} +toast_error_loading_rxdata = Failed to load {$file_path}: {$why} +toast_info_saving_proj = Saving project... +toast_info_saved_proj = Saved project successfully! +toast_info_opened_proj = Opened project successfully! +toast_info_successful_load = Successfully opened {$projectName} \ No newline at end of file diff --git a/src/cache/data.rs b/src/cache/data.rs index d7d59968..180d632b 100644 --- a/src/cache/data.rs +++ b/src/cache/data.rs @@ -172,7 +172,6 @@ impl Cache { tilesets, troops, weapons, - maps: Default::default(), scripts: AtomicRefCell::new(scripts), }; diff --git a/src/command_gen/mod.rs b/src/command_gen/mod.rs index 1e30f480..db32d3ed 100644 --- a/src/command_gen/mod.rs +++ b/src/command_gen/mod.rs @@ -18,7 +18,7 @@ use command_lib::{CommandDescription, CommandKind, Index, Parameter}; use ui_example::UiExample; -use crate::prelude::*; +use crate::{fl, prelude::*}; pub mod parameter_ui; pub mod ui_example; @@ -82,7 +82,7 @@ impl CommandGeneratorWindow { impl window::Window for CommandGeneratorWindow { fn name(&self) -> String { - String::from("Luminol Command Maker") + fl!("window_commandgen_title_label") } fn id(&self) -> egui::Id { @@ -94,19 +94,20 @@ impl window::Window for CommandGeneratorWindow { egui::ScrollArea::both().show(ui, |ui| { let mut del_index = None; for (idx, command) in self.commands.iter_mut().enumerate() { - ui.push_id(command.guid, |ui| { - let header = egui::collapsing_header::CollapsingState::load_with_default_open( - ui.ctx(), - format!("command_{idx}").into(), - false, - ); + ui.push_id(command.guid, |ui| { + let header = + egui::collapsing_header::CollapsingState::load_with_default_open( + ui.ctx(), + format!("command_{idx}").into(), + false, + ); header .show_header(ui, |ui| { ui.horizontal(|ui| { - ui.label("Name:"); + ui.label(format!("{}:", fl!("name"))); ui.text_edit_singleline(&mut command.name); - ui.label("Code:"); + ui.label(format!("{}:", fl!("code"))); ui.add(egui::DragValue::new(&mut command.code)); }); @@ -122,56 +123,78 @@ impl window::Window for CommandGeneratorWindow { } }) .body(|ui| { - ui.label("Description:"); + ui.label(format!("{}:", fl!("description"))); ui.text_edit_multiline(&mut command.description) - .on_hover_text("Description for this command"); - ui.label("Lumi help text"); - ui.text_edit_multiline(&mut command.lumi_text).on_hover_text("This text will be shown by lumi if she's enabled"); + .on_hover_text(fl!("window_commandgen_desc_label")); + ui.label(fl!("window_commandgen_lumi_label")); + ui.text_edit_multiline(&mut command.lumi_text) + .on_hover_text(fl!("window_commandgen_lumi_onhover_label")); ui.separator(); - ui.label("Type"); + ui.label(fl!("type")); ui.horizontal(|ui| { ui.menu_button( format!("{} ⏷", <&str>::from(&command.kind)), |ui| { for kind in CommandKind::iter() { - let text =<&str>::from(&kind); - ui.selectable_value( - &mut command.kind, - kind, - text, - ); + let text = <&str>::from(&kind); + ui.selectable_value(&mut command.kind, kind, text); } }, ); match command.kind { - CommandKind::Multi { ref mut code, ref mut highlight} =>{ - ui.label("Cont. Code").on_hover_text("Luminol will assume that any following commands with this code are a part of this one"); + CommandKind::Multi { + ref mut code, + ref mut highlight, + } => { + ui.label(fl!("window_commandgen_contcode_label")) + .on_hover_text(fl!( + "window_commandgen_contcode_onhover_label" + )); ui.add(egui::DragValue::new(code)); - ui.checkbox(highlight, "Enable ruby syntax highlighting"); + ui.checkbox( + highlight, + fl!("window_commandgen_syntax_highlighting_cb"), + ); } - CommandKind::Branch { ref mut end_code, .. } => { - ui.label("End Code").on_hover_text("Luminol will add this command to denote the end of the branch"); + CommandKind::Branch { + ref mut end_code, .. + } => { + ui.label(fl!("window_commandgen_endcode_label")) + .on_hover_text(fl!( + "window_commandgen_endcode_onhover_label" + )); ui.add(egui::DragValue::new(end_code)); } _ => {} } }); - ui.checkbox(&mut command.hidden, "Hide in menu"); + ui.checkbox(&mut command.hidden, fl!("window_commandgen_him_cb")); ui.separator(); - if let CommandKind::Single(ref mut parameters) | CommandKind::Branch { ref mut parameters, .. } = command.kind { - ui.collapsing("Parameters", |ui| { + if let CommandKind::Single(ref mut parameters) + | CommandKind::Branch { + ref mut parameters, .. + } = command.kind + { + ui.collapsing(fl!("parameters"), |ui| { let mut del_idx = None; let mut passed_index = 0; for (ele, parameter) in parameters.iter_mut().enumerate() { - parameter_ui::parameter_ui(ui, parameter, (ele, &mut del_idx)); - - Self::recalculate_parameter_index(parameter, &mut passed_index); + parameter_ui::parameter_ui( + ui, + parameter, + (ele, &mut del_idx), + ); + + Self::recalculate_parameter_index( + parameter, + &mut passed_index, + ); } if let Some(idx) = del_idx { @@ -192,7 +215,9 @@ impl window::Window for CommandGeneratorWindow { } }); - if command.parameter_count() > 0 && ui.button("Preview UI").clicked() { + if command.parameter_count() > 0 + && ui.button(fl!("window_commandgen_preview_btn")).clicked() + { self.ui_examples.push(UiExample::new(command)); } @@ -206,17 +231,17 @@ impl window::Window for CommandGeneratorWindow { ui.horizontal(|ui| { if ui - .button( - egui::RichText::new("+") - .monospace() - .color(egui::Color32::GREEN), - ) - .clicked() + .button( + egui::RichText::new("+") + .monospace() + .color(egui::Color32::GREEN), + ) + .clicked() { self.commands.push(CommandDescription::default()); } - if ui.button("Save").clicked() { + if ui.button(fl!("save")).clicked() { command_db!().user = self.commands.clone(); } }); diff --git a/src/command_gen/parameter_ui.rs b/src/command_gen/parameter_ui.rs index f7eb7de0..0e04eda5 100644 --- a/src/command_gen/parameter_ui.rs +++ b/src/command_gen/parameter_ui.rs @@ -27,49 +27,54 @@ use eframe::egui; use strum::IntoEnumIterator; +use crate::fl; + pub fn parameter_ui( ui: &mut egui::Ui, parameter: &mut Parameter, del_idx: (usize, &mut Option), ) { ui.horizontal(|ui| { - ui.menu_button(format!("{} ⏷", <&str>::from(&*parameter)), |ui| { - for iter_kind in Parameter::iter() { - if let Parameter::Group {ref mut guid , ..} - | Parameter::Selection { ref mut guid, .. } = parameter { - *guid = rand::random(); - } - let text: &str = (&iter_kind).into(); - ui.selectable_value(parameter, iter_kind, text); + ui.menu_button(format!("{} ⏷", <&str>::from(&*parameter)), |ui| { + for iter_kind in Parameter::iter() { + if let Parameter::Group { ref mut guid, .. } + | Parameter::Selection { ref mut guid, .. } = parameter + { + *guid = rand::random(); } - }); + let text: &str = (&iter_kind).into(); + ui.selectable_value(parameter, iter_kind, text); + } + }); - if let Parameter::Single { ref mut index, ..} - | Parameter::Selection { ref mut index, .. } = parameter { - ui.label("Position: ").on_hover_text_at_pointer("Position of this parameter, when not set it is assumed to be the index of the parameter"); - match index { - Index::Overridden(ref mut idx) => { - ui.add(egui::DragValue::new(idx)); - } - Index::Assumed(ref mut assumed_idx) => { - if ui.add(egui::DragValue::new(assumed_idx)).changed() { - *index = Index::Overridden(*assumed_idx); - } + if let Parameter::Single { ref mut index, .. } + | Parameter::Selection { ref mut index, .. } = parameter + { + ui.label(format!("{}: ", fl!("position"))) + .on_hover_text_at_pointer(fl!("window_commandgen_position_onhover_label")); + match index { + Index::Overridden(ref mut idx) => { + ui.add(egui::DragValue::new(idx)); + } + Index::Assumed(ref mut assumed_idx) => { + if ui.add(egui::DragValue::new(assumed_idx)).changed() { + *index = Index::Overridden(*assumed_idx); } } } + } - if ui - .button( - egui::RichText::new("-") - .monospace() - .color(egui::Color32::RED), - ) - .clicked() - { - *del_idx.1 = Some(del_idx.0); - } - }); + if ui + .button( + egui::RichText::new("-") + .monospace() + .color(egui::Color32::RED), + ) + .clicked() + { + *del_idx.1 = Some(del_idx.0); + } + }); match parameter { Parameter::Group { @@ -77,7 +82,7 @@ pub fn parameter_ui( guid, } => { ui.push_id(guid, |ui| { - egui::CollapsingHeader::new("Grouped parameters") + egui::CollapsingHeader::new(fl!("window_commandgen_grouped_params_label")) .default_open(true) .show(ui, |ui| { let mut del_idx = None; @@ -101,7 +106,7 @@ pub fn parameter_ui( } }) .header_response - .on_hover_text("This parameter groups together other parameters"); + .on_hover_text(fl!("window_commandgen_grouped_params_onhover_label")); }); } Parameter::Selection { @@ -110,7 +115,7 @@ pub fn parameter_ui( .. } => { ui.push_id(guid, |ui| { - egui::CollapsingHeader::new("Subparameters") + egui::CollapsingHeader::new(fl!("window_commandgen_subparams_label")) .default_open(true) .show(ui, |ui| { let mut del_idx = None; @@ -142,7 +147,7 @@ pub fn parameter_ui( } }) .header_response - .on_hover_text("This parameter selects one of the following parameters"); + .on_hover_text(fl!("window_commandgen_subparams_onhover_label")); }); } Parameter::Single { @@ -152,18 +157,18 @@ pub fn parameter_ui( .. } => { ui.horizontal(|ui| { - ui.label("Name"); + ui.label(fl!("name")); ui.text_edit_singleline(name); }); ui.horizontal(|ui| { - ui.label("Description:"); + ui.label(format!("{}:", fl!("description"))); ui.text_edit_singleline(description) - .on_hover_text("Description for this parameter"); + .on_hover_text(fl!("window_commandgen_description_onhover_label")); }); ui.horizontal(|ui| { - ui.label("Type: "); + ui.label(format!("{}: ", fl!("type"))); ui.menu_button(format!("{} ⏷", <&str>::from(&*kind)), |ui| { for iter_kind in ParameterKind::iter() { let text: &str = (&iter_kind).into(); @@ -173,7 +178,7 @@ pub fn parameter_ui( }); if let ParameterKind::Enum { ref mut variants } = kind { - egui::CollapsingHeader::new("Variants") + egui::CollapsingHeader::new(fl!("variants")) .default_open(true) .show(ui, |ui| { let mut del_idx = None; @@ -211,7 +216,7 @@ pub fn parameter_ui( } }) .header_response - .on_disabled_hover_text("Variants for the enum"); + .on_disabled_hover_text(fl!("window_commandgen_variants_onhover_label")); } } Parameter::Dummy => {} diff --git a/src/command_gen/ui_example.rs b/src/command_gen/ui_example.rs index a7e19a10..b81c6154 100644 --- a/src/command_gen/ui_example.rs +++ b/src/command_gen/ui_example.rs @@ -25,6 +25,8 @@ use command_lib::{CommandDescription, CommandKind, Parameter, ParameterKind}; use eframe::egui; +use crate::fl; + pub struct UiExample { command: CommandDescription, } @@ -38,9 +40,10 @@ impl UiExample { pub fn update(&mut self, ctx: &egui::Context) -> bool { let mut open = true; - egui::Window::new(format!( - "[{}] {} UI example", - self.command.code, self.command.name + egui::Window::new(fl!( + "window_commandgen_ui_example_label", + code = self.command.code, + name = self.command.name.clone() )) .open(&mut open) .show(ctx, |ui| { @@ -104,10 +107,20 @@ impl UiExample { match kind { ParameterKind::Switch => { - ui.button("Switch: [000: EXAMPLE]").clicked(); + ui.button(format!( + "{}: [000: {}]", + fl!("switch"), + fl!("example_allcaps") + )) + .clicked(); } ParameterKind::Variable => { - ui.button("Variable [000: EXAMPLE]").clicked(); + ui.button(format!( + "{} [000: {}]", + fl!("variable"), + fl!("example_allcaps") + )) + .clicked(); } ParameterKind::String => { ui.text_edit_singleline(&mut "".to_string()); diff --git a/src/components/top_bar.rs b/src/components/top_bar.rs index d5054a56..aa6dd1df 100644 --- a/src/components/top_bar.rs +++ b/src/components/top_bar.rs @@ -22,6 +22,7 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. +use crate::fl; use crate::prelude::*; use crate::Pencil; @@ -41,7 +42,7 @@ impl TopBar { let state = state!(); egui::widgets::global_dark_light_mode_switch(ui); - ui.checkbox(&mut self.fullscreen, "Fullscreen"); + ui.checkbox(&mut self.fullscreen, fl!("fullscreen")); frame.set_fullscreen(self.fullscreen); @@ -55,40 +56,40 @@ impl TopBar { ui.separator(); - ui.menu_button("File", |ui| { + ui.menu_button(fl!("topbar_file_section"), |ui| { ui.label(if let Some(path) = state.filesystem.project_path() { - format!("Current project:\n{}", path) + fl!("topbar_file_current_proj_label", path = path.to_string()) } else { - "No project open".to_string() + fl!("topbar_file_no_proj_open_label") }); - if ui.button("New Project").clicked() { + if ui.button(fl!("new_project")).clicked() { state.windows.add_window(new_project::Window::default()); } - open_project |= ui.button("Open Project").clicked(); + open_project |= ui.button(fl!("open_project")).clicked(); ui.separator(); ui.add_enabled_ui(state.filesystem.project_loaded(), |ui| { - if ui.button("Project Config").clicked() { + if ui.button(fl!("topbar_file_proj_config_btn")).clicked() { state.windows.add_window(config_window::Window {}); } - if ui.button("Close Project").clicked() { + if ui.button(fl!("topbar_file_close_proj_btn")).clicked() { state.windows.clean_windows(); state.tabs.clean_tabs(|t| !t.requires_filesystem()); state.audio.clear_sinks(); // audio loads files borrows from the filesystem. unloading while they are playing is a crash state.filesystem.unload_project(); } - save_project |= ui.button("Save Project").clicked(); + save_project |= ui.button(fl!("topbar_file_save_proj_btn")).clicked(); }); ui.separator(); ui.add_enabled_ui(state.filesystem.project_loaded(), |ui| { - if ui.button("Command Maker").clicked() { + if ui.button(fl!("topbar_file_command_maker_btn")).clicked() { state .windows .add_window(crate::command_gen::CommandGeneratorWindow::default()); @@ -97,7 +98,7 @@ impl TopBar { ui.separator(); - if ui.button("Quit").clicked() { + if ui.button(fl!("topbar_file_quit_btn")).clicked() { frame.close(); } }); @@ -119,27 +120,27 @@ impl TopBar { ui.separator(); - ui.menu_button("Data", |ui| { + ui.menu_button(fl!("topbar_data_section"), |ui| { ui.add_enabled_ui(state.filesystem.project_loaded(), |ui| { - if ui.button("Maps").clicked() { + if ui.button(fl!("maps")).clicked() { state.windows.add_window(map_picker::Window::default()); } - if ui.button("Items").clicked() { + if ui.button(fl!("items")).clicked() { state.windows.add_window(items::Window::default()); } - if ui.button("Common Events").clicked() { + if ui.button(fl!("common_events")).clicked() { state .windows .add_window(common_event_edit::Window::default()); } - if ui.button("Scripts").clicked() { + if ui.button(fl!("scripts")).clicked() { state.windows.add_window(script_edit::Window::default()); } - if ui.button("Sound Test").clicked() { + if ui.button(fl!("scripts")).clicked() { state.windows.add_window(sound_test::Window::default()); } }); @@ -160,12 +161,12 @@ impl TopBar { state.windows.add_window(misc::EguiInspection::default()); } - if ui.button("Egui Memory").clicked() { + if ui.button(fl!("topbar_egui_memory_btn")).clicked() { state.windows.add_window(misc::EguiMemory::default()); } let mut debug_on_hover = ui.ctx().debug_on_hover(); - ui.toggle_value(&mut debug_on_hover, "Debug on hover"); + ui.toggle_value(&mut debug_on_hover, fl!("topbar_debug_on_hover_tv")); ui.ctx().set_debug_on_hover(debug_on_hover); ui.separator(); @@ -178,7 +179,7 @@ impl TopBar { ui.separator(); ui.add_enabled_ui(state.filesystem.project_loaded(), |ui| { - if ui.button("Playtest").clicked() { + if ui.button(fl!("topbar_playtest_btn")).clicked() { let mut cmd = luminol_term::CommandBuilder::new("steamshim"); cmd.cwd(state.filesystem.project_path().expect("project not loaded")); @@ -191,13 +192,13 @@ impl TopBar { match result { Ok(w) => state.windows.add_window(w), - Err(e) => state.toasts.error(format!( - "error starting game (tried steamshim.exe and then game.exe): {e}" - )), + Err(e) => state + .toasts + .error(fl!("toast_error_starting_game", why = e.to_string())), } } - if ui.button("Terminal").clicked() { + if ui.button(fl!("topbar_terminal_btn")).clicked() { #[cfg(windows)] let shell = "powershell"; #[cfg(unix)] @@ -207,14 +208,16 @@ impl TopBar { match crate::windows::console::Console::new(cmd) { Ok(w) => state.windows.add_window(w), - Err(e) => state.toasts.error(format!("error starting shell: {e}")), + Err(e) => state + .toasts + .error(fl!("toast_error_starting_shell", why = e.to_string())), } } }); ui.separator(); - ui.label("Brush:"); + ui.label(format!("{}:", fl!("topbar_brush_label"))); let mut toolbar = state.toolbar.borrow_mut(); for brush in Pencil::iter() { @@ -228,9 +231,9 @@ impl TopBar { } if save_project { - state.toasts.info("Saving project..."); + state.toasts.info(fl!("toast_info_saving_proj")); match state.data_cache.save() { - Ok(_) => state.toasts.info("Saved project sucessfully!"), + Ok(_) => state.toasts.info(fl!("toast_info_saved_proj")), Err(e) => state.toasts.error(e), } } @@ -238,7 +241,7 @@ impl TopBar { if self.open_project_promise.is_some() { if let Some(r) = self.open_project_promise.as_ref().unwrap().ready() { match r { - Ok(_) => state.toasts.info("Opened project successfully!"), + Ok(_) => state.toasts.info(fl!("toast_info_opened_proj")), Err(e) => state.toasts.error(e), } self.open_project_promise = None; diff --git a/src/filesystem/project.rs b/src/filesystem/project.rs index 7db46846..3fe873fc 100644 --- a/src/filesystem/project.rs +++ b/src/filesystem/project.rs @@ -14,7 +14,7 @@ // // You should have received a copy of the GNU General Public License // along with Luminol. If not, see . -use crate::prelude::*; +use crate::{fl, prelude::*}; use super::FileSystem as FileSystemTrait; use super::{archiver, host, list, path_cache, DirEntry, Error, Metadata, OpenFlags}; @@ -310,7 +310,7 @@ impl FileSystem { let state = self.state.borrow(); match &*state { State::Unloaded => { - ui.label("Unloaded"); + ui.label(fl!("unloaded")); } State::HostLoaded(fs) => { ui.label("Host Filesystem Loaded"); diff --git a/src/i18n.rs b/src/i18n.rs new file mode 100644 index 00000000..1087fd8f --- /dev/null +++ b/src/i18n.rs @@ -0,0 +1,55 @@ +// Copyright (C) 2023 Lily Lyons +// +// This file is part of Luminol. +// +// Luminol is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Luminol is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Luminol. If not, see . +use i18n_embed::{ + fluent::{fluent_language_loader, FluentLanguageLoader}, + DesktopLanguageRequester, I18nEmbedError, +}; +use once_cell::sync::Lazy; +use rust_embed::RustEmbed; + +#[derive(Debug, RustEmbed)] +#[folder = "lang"] +pub struct Localizations; + +static LOADER: Lazy = Lazy::new(|| { + let loader = fluent_language_loader!(); + let requested_languages = DesktopLanguageRequester::requested_languages(); + let _ = i18n_embed::select(&loader, &Localizations, &requested_languages); + + loader +}); +pub fn language_loader() -> &'static FluentLanguageLoader { + &LOADER +} +pub fn set_language(code: IsoCode) -> Result<(), I18nEmbedError> { + i18n_embed::select( + language_loader(), + &Localizations, + &[code.to_string().parse().unwrap()], + )?; + Ok(()) +} + +#[macro_export] +macro_rules! fl { + ($message_id:literal) => { + i18n_embed_fl::fl!($crate::i18n::language_loader(), $message_id) + }; + ($message_id:literal, $($arg:tt)*) => { + i18n_embed_fl::fl!($crate::i18n::language_loader(), $message_id, $($arg)*) + } +} diff --git a/src/lib.rs b/src/lib.rs index 39c1fa55..31fac287 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -95,6 +95,8 @@ pub mod steam; pub mod graphics; +pub mod i18n; + pub use luminol::Luminol; use tabs::tab::Tab; diff --git a/src/main.rs b/src/main.rs index 753ecdac..e2ff240e 100644 --- a/src/main.rs +++ b/src/main.rs @@ -25,6 +25,8 @@ // Program grant you additional permission to convey the resulting work. #![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] // hide console window on Windows in release +use luminol::fl; + fn main() { #[cfg(feature = "steamworks")] if let Err(e) = luminol::steam::Steamworks::setup() { @@ -45,26 +47,32 @@ fn main() { std::thread::sleep(std::time::Duration::from_secs(5)); let deadlocks = parking_lot::deadlock::check_deadlock(); + if deadlocks.is_empty() { continue; } rfd::MessageDialog::new() - .set_title("Fatal Error") + .set_title(fl!("fatal_error")) .set_level(rfd::MessageLevel::Error) - .set_description(&format!( - "Luminol has deadlocked! Please file an issue.\n{} deadlocks detected", - deadlocks.len() + .set_description(fl!( + "deadlock_detected_description", + numOfDeadLocks = deadlocks.len() )) .show(); for (i, threads) in deadlocks.iter().enumerate() { let mut description = String::new(); for t in threads { - writeln!(description, "Thread Id {:#?}", t.thread_id()).unwrap(); + writeln!( + description, + "{}", + fl!("thread_id", id = format!("{:#?}", t.thread_id())) + ) + .unwrap(); writeln!(description, "{:#?}", t.backtrace()).unwrap(); } rfd::MessageDialog::new() - .set_title(&format!("Deadlock #{i}")) + .set_title(fl!("deadlock_detected_title", deadlockIndex = i)) .set_level(rfd::MessageLevel::Error) .set_description(&description) .show(); @@ -111,7 +119,7 @@ fn main() { }; eframe::run_native( - "Luminol", + &fl!("luminol"), native_options, Box::new(|cc| Box::new(luminol::Luminol::new(cc, std::env::args_os().nth(1)))), ) diff --git a/src/modals/switch.rs b/src/modals/switch.rs index 4888e6d7..c50f0c08 100644 --- a/src/modals/switch.rs +++ b/src/modals/switch.rs @@ -22,7 +22,7 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. -use crate::prelude::*; +use crate::{fl, prelude::*}; /// The switch picker modal. pub struct Modal { @@ -69,7 +69,7 @@ impl modal::Modal for Modal { fn show(&mut self, ctx: &egui::Context, open: &mut bool, data: &mut Self::Data) { let mut win_open = true; - egui::Window::new("Switch Picker") + egui::Window::new(fl!("modal_switch_title_label")) .id(self.id) .resizable(false) .open(&mut win_open) @@ -114,8 +114,8 @@ impl modal::Modal for Modal { }); ui.horizontal(|ui| { - *open = !ui.button("Ok").clicked(); - *open = !ui.button("Cancel").clicked(); + *open = !ui.button(fl!("ok")).clicked(); + *open = !ui.button(fl!("cancel")).clicked(); if ui .add( @@ -127,7 +127,7 @@ impl modal::Modal for Modal { memory.1 = memory.0; }; egui::TextEdit::singleline(&mut memory.2) - .hint_text("Search 🔎") + .hint_text(format!("{} 🔎", fl!("search"))) .show(ui); }); diff --git a/src/modals/variable.rs b/src/modals/variable.rs index 09cdb7d2..6d478a58 100644 --- a/src/modals/variable.rs +++ b/src/modals/variable.rs @@ -22,7 +22,7 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. -use crate::prelude::*; +use crate::{fl, prelude::*}; /// The variable picker modal. pub struct Modal { @@ -71,7 +71,7 @@ impl modal::Modal for Modal { fn show(&mut self, ctx: &egui::Context, open: &mut bool, data: &mut Self::Data) { let mut win_open = true; - egui::Window::new("Variable Picker") + egui::Window::new(fl!("modal_variable_title_label")) .id(self.id) .resizable(false) .open(&mut win_open) @@ -130,7 +130,7 @@ impl modal::Modal for Modal { memory.1 = memory.0; }; egui::TextEdit::singleline(&mut memory.2) - .hint_text("Search 🔎") + .hint_text(format!("{} 🔎", fl!("search"))) .show(ui); }); diff --git a/src/prelude.rs b/src/prelude.rs index db5b7894..f90abc3d 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -71,3 +71,5 @@ pub use rmxp_types::*; #[cfg(feature = "steamworks")] pub use crate::steam::Steamworks; + +pub use crate::fl; diff --git a/src/tabs/map.rs b/src/tabs/map.rs index 14295b39..82a423d7 100644 --- a/src/tabs/map.rs +++ b/src/tabs/map.rs @@ -23,6 +23,7 @@ // Program grant you additional permission to convey the resulting work. #![allow(unused_imports)] +use crate::{fl, prelude::*}; use egui::Pos2; use std::{cell::RefMut, collections::HashMap, collections::VecDeque}; @@ -318,7 +319,11 @@ impl Tab { impl tab::Tab for Tab { fn name(&self) -> String { let mapinfos = state!().data_cache.mapinfos(); - format!("Map {}: {}", self.id, mapinfos[&self.id].name) + fl!( + "tab_map_title_label", + id = self.id, + name = mapinfos[&self.id].name.clone() + ) } fn id(&self) -> egui::Id { @@ -335,7 +340,7 @@ impl tab::Tab for Tab { ui.horizontal_wrapped(|ui| { ui.add( egui::Slider::new(&mut self.view.scale, 15.0..=300.) - .text("Scale") + .text(fl!("scale")) .fixed_decimals(0), ); @@ -344,15 +349,19 @@ impl tab::Tab for Tab { ui.menu_button( // Format the text based on what layer is selected. match self.view.selected_layer { - SelectedLayer::Events => "Events ⏷".to_string(), - SelectedLayer::Tiles(layer) => format!("Layer {} ⏷", layer + 1), + SelectedLayer::Events => format!("{} ⏷", fl!("events")), + SelectedLayer::Tiles(layer) => { + format!("{} ⏷", fl!("tab_map_layer_section_sv", num = layer)) + } }, |ui| { // TODO: Add layer enable button // Display all layers. ui.columns(2, |columns| { columns[1].visuals_mut().button_frame = true; - columns[0].label(egui::RichText::new("Panorama").underline()); + columns[0].label( + egui::RichText::new(fl!("tab_map_panorama_label")).underline(), + ); columns[1].checkbox(&mut self.view.map.pano_enabled, "👁"); for (index, layer) in @@ -361,7 +370,7 @@ impl tab::Tab for Tab { columns[0].selectable_value( &mut self.view.selected_layer, SelectedLayer::Tiles(index), - format!("Layer {}", index + 1), + fl!("tab_map_layer_section_sv", num = (index + 1)), ); columns[1].checkbox(layer, "👁"); } @@ -370,7 +379,7 @@ impl tab::Tab for Tab { columns[0].selectable_value( &mut self.view.selected_layer, SelectedLayer::Events, - egui::RichText::new("Events").italics(), + egui::RichText::new(fl!("events")).italics(), ); columns[1].checkbox(&mut self.view.event_enabled, "👁"); @@ -382,9 +391,9 @@ impl tab::Tab for Tab { ui.separator(); - ui.checkbox(&mut self.view.visible_display, "Display Visible Area") + ui.checkbox(&mut self.view.visible_display, fl!("tab_map_dva_cb")) .on_hover_text("Display the visible area in-game (640x480)"); - ui.checkbox(&mut self.view.move_preview, "Preview event move routes") + ui.checkbox(&mut self.view.move_preview, fl!("tab_map_pemr_cb")) .on_hover_text("Preview event page move routes"); ui.checkbox(&mut self.view.snap_to_grid, "Snap to grid") .on_hover_text("Snap's the viewport to the tile grid"); @@ -399,8 +408,7 @@ impl tab::Tab for Tab { self.tilemap.save_to_disk(); } - if map.preview_move_route.is_some() - && ui.button("Clear move route preview").clicked() + if map.preview_move_route.is_some() && ui.button(fl!("tab_map_cmrp_btn")).clicked() { map.preview_move_route = None; } diff --git a/src/tabs/started.rs b/src/tabs/started.rs index f7002963..6f370892 100644 --- a/src/tabs/started.rs +++ b/src/tabs/started.rs @@ -22,7 +22,7 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. -use crate::prelude::*; +use crate::{fl, prelude::*}; /// The Luminol "get started screen" similar to vscode's. #[derive(Default)] @@ -44,7 +44,7 @@ impl Tab { impl tab::Tab for Tab { fn name(&self) -> String { - "Get Started".to_string() + fl!("tab_started_title_label") } fn id(&self) -> egui::Id { @@ -54,14 +54,14 @@ impl tab::Tab for Tab { fn show(&mut self, ui: &mut egui::Ui) { let state = state!(); ui.label( - egui::RichText::new("Luminol") + egui::RichText::new(fl!("luminol")) .size(40.) .color(egui::Color32::LIGHT_GRAY), ); ui.add_space(100.); - ui.heading("Start"); + ui.heading(fl!("start")); if self .load_project_promise @@ -71,7 +71,7 @@ impl tab::Tab for Tab { ui.spinner(); } else { if ui - .button(egui::RichText::new("New Project").size(20.)) + .button(egui::RichText::new(fl!("new_project")).size(20.)) .clicked() { state!() @@ -79,21 +79,19 @@ impl tab::Tab for Tab { .add_window(crate::windows::new_project::Window::default()); } if ui - .button(egui::RichText::new("Open Project").size(20.)) + .button(egui::RichText::new(fl!("open_project")).size(20.)) .clicked() { self.load_project_promise = Some(Promise::spawn_local(async move { if let Err(e) = state.filesystem.spawn_project_file_picker().await { - state - .toasts - .error(format!("Error loading the project: {e}")); + state.toasts.error(fl!("toast_error_load_proj", why = e)); } })); } ui.add_space(100.); - ui.heading("Recent"); + ui.heading(fl!("tab_started_recent_projects_label")); for path in &global_config!().recent_projects { if ui.button(path).clicked() { @@ -101,16 +99,15 @@ impl tab::Tab for Tab { self.load_project_promise = Some(Promise::spawn_local(async move { if let Err(why) = state.filesystem.load_project(path) { - state - .toasts - .error(format!("Error loading the project: {why}")); + state.toasts.error(fl!("toast_error_load_proj", why = why)); } else { - state!().toasts.info(format!( - "Successfully opened {:?}", - state!() + state!().toasts.info(fl!( + "toast_info_successful_load", + projectName = state!() .filesystem .project_path() .expect("project not open") + .to_string() )); } })); diff --git a/src/windows/about.rs b/src/windows/about.rs index 081e0678..ad63e339 100644 --- a/src/windows/about.rs +++ b/src/windows/about.rs @@ -22,6 +22,8 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. +use crate::fl; + /// A basic about window. /// Shows some info on Luminol, along with an icon. pub struct Window { @@ -42,7 +44,7 @@ impl Default for Window { impl super::window::Window for Window { fn name(&self) -> String { - "About".to_string() + fl!("window_about_title_label") } fn id(&self) -> egui::Id { @@ -51,7 +53,7 @@ impl super::window::Window for Window { fn show(&mut self, ctx: &egui::Context, open: &mut bool) { // Show the window. Name it "About Luminol" - egui::Window::new("About Luminol") + egui::Window::new(fl!("window_about_luminol_label")) // Open is passed in. egui sets it to false if the window is closed. .open(open) .resizable(false) @@ -59,19 +61,22 @@ impl super::window::Window for Window { // Center the widgets vertically for cleanliness. ui.vertical_centered(|ui| { self.icon.show_scaled(ui, 0.5); // We scale the icon down since it's pretty huge. - ui.heading("Luminol"); + ui.heading(fl!("luminol")); ui.separator(); - ui.label(format!("Luminol version {}", env!("CARGO_PKG_VERSION"))); + ui.label(fl!( + "window_about_version_text_label", + version = env!("CARGO_PKG_VERSION") + )); ui.label(format!("git-rev {}", git_version::git_version!())); ui.separator(); - ui.label("Luminol is a FOSS version of the RPG Maker XP editor."); + ui.label(fl!("window_about_description_text_label")); ui.separator(); - ui.label(format!( - "Authors: \n{}", - env!("CARGO_PKG_AUTHORS").replace(':', "\n") + ui.label(fl!( + "window_about_authors_label", + authorsArray = env!("CARGO_PKG_AUTHORS").replace(':', "\n") )) }) }); diff --git a/src/windows/common_event_edit.rs b/src/windows/common_event_edit.rs index 7b4a972b..20cc7f50 100644 --- a/src/windows/common_event_edit.rs +++ b/src/windows/common_event_edit.rs @@ -22,7 +22,7 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. -use crate::prelude::*; +use crate::{fl, prelude::*}; /// The common event editor. pub struct Window { @@ -43,8 +43,8 @@ impl window::Window for Window { fn name(&self) -> String { self.tabs .focused_name() - .map_or("Common Events".to_string(), |name| { - format!("Editing Common Event {name}") + .map_or(fl!("common_events"), |name| { + fl!("window_common_events_editing_label", name = name) }) } @@ -120,9 +120,13 @@ impl tab::Tab for CommonEventTab { fn show(&mut self, ui: &mut egui::Ui) { ui.horizontal(|ui| { - let trigger_types = ["None", "Autorun", "Parallel"]; + let trigger_types = [ + fl!("window_common_events_type_none_sv"), + fl!("window_common_events_type_autorun_sv"), + fl!("window_common_events_type_parallel_sv"), + ]; egui::ComboBox::new(format!("common_event_{}_trigger", self.event.id), "Trigger") - .selected_text(trigger_types[self.event.trigger]) + .selected_text(trigger_types[self.event.trigger].clone()) .show_ui(ui, |ui| { for (ele, trigger) in trigger_types.into_iter().enumerate() { ui.selectable_value(&mut self.event.trigger, ele, trigger); @@ -136,16 +140,16 @@ impl tab::Tab for CommonEventTab { let mut save_event = false; - if ui.button("Ok").clicked() { + if ui.button(fl!("ok")).clicked() { save_event = true; self.force_close = true; } - if ui.button("Cancel").clicked() { + if ui.button(fl!("cancel")).clicked() { self.force_close = true; } - if ui.button("Apply").clicked() { + if ui.button(fl!("apply")).clicked() { save_event = true; } @@ -155,7 +159,7 @@ impl tab::Tab for CommonEventTab { common_events[self.event.id - 1] = self.event.clone(); } - ui.label("Name"); + ui.label(fl!("name")); ui.text_edit_singleline(&mut self.event.name); }); diff --git a/src/windows/config_window.rs b/src/windows/config_window.rs index 58e5ae81..c715aee6 100644 --- a/src/windows/config_window.rs +++ b/src/windows/config_window.rs @@ -22,7 +22,7 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. -use crate::prelude::*; +use crate::{fl, prelude::*}; /// The confg window pub struct Window {} @@ -31,7 +31,7 @@ impl Window {} impl window::Window for Window { fn name(&self) -> String { - "Local Luminol Config".to_string() + fl!("window_config_title_label") } fn id(&self) -> egui::Id { @@ -42,12 +42,12 @@ impl window::Window for Window { egui::Window::new(self.name()).open(open).show(ctx, |ui| { let mut config = project_config!(); - ui.label("Project name"); + ui.label(fl!("window_config_proj_name_label")); ui.text_edit_singleline(&mut config.project_name); - ui.label("Scripts path"); + ui.label(fl!("window_config_scripts_path_label")); ui.text_edit_singleline(&mut config.scripts_path); - ui.checkbox(&mut config.use_ron, "Use RON (Rusty Object Notation)"); - egui::ComboBox::from_label("RGSS Version") + ui.checkbox(&mut config.use_ron, fl!("window_config_use_ron_cb")); + egui::ComboBox::from_label(fl!("window_config_rgss_ver_label")) .selected_text(config.rgss_ver.to_string()) .show_ui(ui, |ui| { for ver in config::RGSSVer::iter() { @@ -55,7 +55,7 @@ impl window::Window for Window { } }); - ui.label("Playtest Executable"); + ui.label(fl!("window_config_playtest_exe_btn")); ui.text_edit_singleline(&mut config.playtest_exe); }); } diff --git a/src/windows/console.rs b/src/windows/console.rs index 831a86db..252afe97 100644 --- a/src/windows/console.rs +++ b/src/windows/console.rs @@ -22,6 +22,8 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. +use crate::fl; + pub struct Console { term: luminol_term::Terminal, } @@ -56,7 +58,7 @@ impl super::window::Window for Console { if let Err(e) = self.term.ui(ui) { crate::state!() .toasts - .error(format!("error displaying terminal: {e:?}")); + .error(fl!("toast_error_displaying_term", why = e.to_string())); } }); } diff --git a/src/windows/event_edit.rs b/src/windows/event_edit.rs index cf740f20..2e323e2d 100644 --- a/src/windows/event_edit.rs +++ b/src/windows/event_edit.rs @@ -22,7 +22,7 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. -use crate::prelude::*; +use crate::{fl, prelude::*}; /// The event editor window. pub struct Window { @@ -80,10 +80,10 @@ impl window::Window for Window { ui.horizontal(|ui| { ui.text_edit_singleline(&mut event.name); - ui.button("New page").clicked(); - ui.button("Copy page").clicked(); - ui.button("Paste page").clicked(); - ui.button("Clear page").clicked(); + ui.button(fl!("window_event_new_page_btn")).clicked(); + ui.button(fl!("window_event_copy_page_btn")).clicked(); + ui.button(fl!("window_event_paste_page_btn")).clicked(); + ui.button(fl!("window_event_clear_page_btn")).clicked(); }); ui.separator(); @@ -102,9 +102,21 @@ impl window::Window for Window { ui.separator(); ui.horizontal(|ui| { - ui.selectable_value(&mut self.viewed_tab, 0, "Configuration"); - ui.selectable_value(&mut self.viewed_tab, 1, "Graphic"); - ui.selectable_value(&mut self.viewed_tab, 2, "Commands"); + ui.selectable_value( + &mut self.viewed_tab, + 0, + fl!("window_event_tab_configuration_sv"), + ); + ui.selectable_value( + &mut self.viewed_tab, + 1, + fl!("window_event_tab_graphic_sv"), + ); + ui.selectable_value( + &mut self.viewed_tab, + 2, + fl!("window_event_tab_commands_sv"), + ); }); ui.separator(); @@ -115,10 +127,13 @@ impl window::Window for Window { 0 => { ui.horizontal(|ui| { ui.vertical(|ui| { - ui.label("Condition"); + ui.label(fl!("window_event_conf_condition_label")); ui.group(|ui| { ui.horizontal(|ui| { - ui.checkbox(&mut page.condition.switch1_valid, "Switch"); + ui.checkbox( + &mut page.condition.switch1_valid, + fl!("window_event_conf_switch_cb"), + ); ui.add_enabled_ui(page.condition.switch1_valid, |ui| { switch::Modal::new( @@ -137,7 +152,10 @@ impl window::Window for Window { }); ui.horizontal(|ui| { - ui.checkbox(&mut page.condition.switch2_valid, "Switch"); + ui.checkbox( + &mut page.condition.switch2_valid, + fl!("window_event_conf_switch_cb"), + ); ui.add_enabled_ui(page.condition.switch2_valid, |ui| { switch::Modal::new( @@ -156,7 +174,10 @@ impl window::Window for Window { }); ui.horizontal(|ui| { - ui.checkbox(&mut page.condition.variable_valid, "Variable"); + ui.checkbox( + &mut page.condition.variable_valid, + fl!("window_event_conf_variable_cb"), + ); ui.add_enabled_ui(page.condition.variable_valid, |ui| { variable::Modal::new( @@ -179,13 +200,13 @@ impl window::Window for Window { &mut page.condition.variable_value, ), ); - ui.label("or above"); + ui.label(fl!("window_event_conf_or_above_label")); }); ui.horizontal(|ui| { ui.checkbox( &mut page.condition.self_switch_valid, - "Self Switch", + fl!("window_event_conf_self_switch_cb"), ); ui.add_enabled_ui(page.condition.self_switch_valid, |ui| { egui::ComboBox::new( @@ -193,7 +214,7 @@ impl window::Window for Window { "event_{}_{}_self_switch_combo", self.id, self.map_id ), - "is on", + fl!("window_event_conf_is_on_label"), ) .selected_text(page.condition.self_switch_ch.clone()) .show_ui( @@ -264,27 +285,58 @@ impl window::Window for Window { ui.horizontal(|ui| { ui.vertical(|ui| { - ui.label("Options"); + ui.label(fl!("window_event_conf_options_label")); ui.group(|ui| { - ui.checkbox(&mut page.step_anime, "Move Animation"); - ui.checkbox(&mut page.walk_anime, "Stop Animation"); - ui.checkbox(&mut page.direction_fix, "Direction Fix"); - ui.checkbox(&mut page.through, "Through"); - ui.checkbox(&mut page.always_on_top, "Always on Top"); + ui.checkbox( + &mut page.step_anime, + fl!("window_event_conf_option_move_anim_cb"), + ); + ui.checkbox( + &mut page.walk_anime, + fl!("window_event_conf_option_stop_anim_cb"), + ); + ui.checkbox( + &mut page.direction_fix, + fl!("window_event_conf_option_direction_fix_cb"), + ); + ui.checkbox( + &mut page.through, + fl!("window_event_conf_option_through_cb"), + ); + ui.checkbox( + &mut page.always_on_top, + fl!("window_event_conf_option_aot_cb"), + ); }); }); ui.vertical(|ui| { - ui.label("Trigger"); + ui.label(fl!("window_event_conf_trigger_label")); ui.group(|ui| { - ui.radio_value(&mut page.trigger, 0, "Action Button"); - ui.radio_value(&mut page.trigger, 1, "Player Touch"); - ui.radio_value(&mut page.trigger, 2, "Event Touch"); - ui.radio_value(&mut page.trigger, 3, "Autorun"); + ui.radio_value( + &mut page.trigger, + 0, + fl!("window_event_conf_trigger_action_btn_rv"), + ); + ui.radio_value( + &mut page.trigger, + 1, + fl!("window_event_conf_trigger_player_touch_rv"), + ); + ui.radio_value( + &mut page.trigger, + 2, + fl!("window_event_conf_trigger_event_touch_rv"), + ); + ui.radio_value( + &mut page.trigger, + 3, + fl!("window_event_conf_trigger_autorun_rv"), + ); ui.radio_value( &mut page.trigger, 4, - "Parallel Process", + fl!("window_event_conf_trigger_parallel_proc_rv"), ); }); }) @@ -314,9 +366,9 @@ impl window::Window for Window { ui.separator(); ui.horizontal(|ui| { - let ok_clicked = ui.button("Ok").clicked(); - let apply_clicked = ui.button("Apply").clicked(); - let cancel_clicked = ui.button("Cancel").clicked(); + let ok_clicked = ui.button(fl!("ok")).clicked(); + let apply_clicked = ui.button(fl!("apply")).clicked(); + let cancel_clicked = ui.button(fl!("cancel")).clicked(); if apply_clicked || ok_clicked { //let mut map = state!().data_cache.map(self.map_id); diff --git a/src/windows/graphic_picker.rs b/src/windows/graphic_picker.rs index 3d71c401..350f8fd9 100644 --- a/src/windows/graphic_picker.rs +++ b/src/windows/graphic_picker.rs @@ -22,7 +22,7 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. -use crate::prelude::*; +use crate::{fl, prelude::*}; pub struct Graphic { pub name: String, @@ -48,9 +48,11 @@ impl Window { { Ok(ri) => ri, Err(why) => { - state!() - .toasts - .error(format!("Cannot load `{icon_path}` icon: {why}")); + state!().toasts.error(fl!( + "toast_error_cannot_load_icon", + icon_path = icon_path.to_string(), + why = why.to_string() + )); continue; } }; @@ -73,7 +75,7 @@ impl Window { } pub fn show(&mut self, ctx: &egui::Context, open: &mut bool, graphic_icon: &mut String) { - egui::Window::new("Graphic Picker") + egui::Window::new(fl!("window_graphic_picker_title_label")) .id(egui::Id::new("icon_picker")) .resize(|res| res.min_width(480.)) .open(open) diff --git a/src/windows/items.rs b/src/windows/items.rs index 1f1dd1df..ab6610ee 100644 --- a/src/windows/items.rs +++ b/src/windows/items.rs @@ -41,7 +41,6 @@ pub struct Window { impl Default for Window { fn default() -> Self { let items = state!().data_cache.items().clone(); - Self { items, selected_item: 0, @@ -56,7 +55,10 @@ impl Default for Window { impl window::Window for Window { fn name(&self) -> String { - format!("Editing item {}", self.items[self.selected_item].name) + fl!( + "window_items_title_label", + name = self.items[self.selected_item].name.clone() + ) } fn id(&self) -> egui::Id { @@ -91,7 +93,7 @@ impl window::Window for Window { .open(open) .show(ctx, |ui| { egui::SidePanel::left(egui::Id::new("item_edit_sidepanel")).show_inside(ui, |ui| { - ui.label("Items"); + ui.label(fl!("items")); egui::ScrollArea::both().max_height(600.).show_rows( ui, ui.text_style_height(&egui::TextStyle::Body), @@ -107,21 +109,21 @@ impl window::Window for Window { }, ); - if ui.button("Change maximum...").clicked() { + if ui.button(fl!("window_items_change_max_btn")).clicked() { eprintln!("`Change maximum...` button trigger"); } }); let selected_item = &mut self.items[self.selected_item]; egui::Grid::new("item_edit_central_grid").show(ui, |ui| { ui.add(Field::new( - "Name", + fl!("name"), egui::TextEdit::singleline(&mut selected_item.name), )); ui.end_row(); ui.add(Field::new( - "Description", + fl!("description"), egui::TextEdit::singleline(&mut selected_item.description), )); ui.end_row(); @@ -130,7 +132,7 @@ impl window::Window for Window { }); if self.menu_se_picker_open { - egui::Window::new("Menu Sound Effect Picker") + egui::Window::new(fl!("window_items_msep_label")) .id(egui::Id::new("menu_se_picker")) .show(ctx, |ui| { self.menu_se_picker.ui(ui); diff --git a/src/windows/map_picker.rs b/src/windows/map_picker.rs index 80d01c41..e7e39d65 100644 --- a/src/windows/map_picker.rs +++ b/src/windows/map_picker.rs @@ -92,7 +92,7 @@ impl window::Window for Window { fn show(&mut self, ctx: &egui::Context, open: &mut bool) { let mut window_open = true; - egui::Window::new("Map Picker") + egui::Window::new(fl!("window_map_picker_title_label")) .open(&mut window_open) .show(ctx, |ui| { egui::ScrollArea::both() @@ -113,7 +113,7 @@ impl window::Window for Window { children_data.entry(0).or_default(); // If there is no `0` entry (i.e. there are no maps) then add one. // Now we can actually render all maps. - egui::CollapsingHeader::new("root") + egui::CollapsingHeader::new(fl!("window_map_picker_root_label")) .default_open(true) .show(ui, |ui| { // There will always be a map `0`. diff --git a/src/windows/misc.rs b/src/windows/misc.rs index 3b4780cd..ef5c563d 100644 --- a/src/windows/misc.rs +++ b/src/windows/misc.rs @@ -22,6 +22,8 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. +use crate::fl; + use super::window::Window; use crate::prelude::*; /// Egui inspection window. @@ -30,7 +32,7 @@ pub struct EguiInspection {} impl Window for EguiInspection { fn name(&self) -> String { - "Egui Inspection".to_string() + fl!("window_egui_inspec_title_label") } fn id(&self) -> egui::Id { @@ -50,7 +52,7 @@ pub struct EguiMemory {} impl Window for EguiMemory { fn name(&self) -> String { - "Egui Memory".to_string() + fl!("window_egui_memory_title_label") } fn id(&self) -> egui::Id { diff --git a/src/windows/new_project.rs b/src/windows/new_project.rs index 7945a2b1..c111c120 100644 --- a/src/windows/new_project.rs +++ b/src/windows/new_project.rs @@ -22,7 +22,7 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. -use crate::prelude::*; +use crate::{fl, prelude::*}; use config::{RGSSVer, RMVer}; use std::io::Read; @@ -52,7 +52,7 @@ struct Progress { impl Default for Window { fn default() -> Self { Self { - name: "My Project".to_string(), + name: fl!("window_new_proj_my_proj_str"), rgss_ver: RGSSVer::RGSS1, editor_ver: RMVer::XP, project_promise: None, @@ -66,7 +66,7 @@ impl Default for Window { impl window::Window for Window { fn name(&self) -> String { - "New Project".to_string() + fl!("new_project") } fn id(&self) -> egui::Id { @@ -79,16 +79,16 @@ impl window::Window for Window { .open(&mut win_open) .show(ctx, |ui| { ui.add_enabled_ui(self.project_promise.is_none(), |ui| { - ui.label("Project Name"); + ui.label(fl!("window_new_proj_name_label")); ui.text_edit_singleline(&mut self.name); - ui.checkbox(&mut self.init_git, "Initialize with git repository"); + ui.checkbox(&mut self.init_git, fl!("window_new_proj_with_git_cb")); ui.add_enabled_ui(self.init_git, |ui| { - ui.label("Git Branch"); + ui.label(fl!("window_new_proj_git_branch_label")); ui.text_edit_singleline(&mut self.git_branch_name); }); - egui::ComboBox::from_label("RGSS runtime") + egui::ComboBox::from_label(fl!("window_new_proj_rgss_runtime_label")) .selected_text(self.rgss_ver.to_string()) .show_ui(ui, |ui| { for ver in RGSSVer::iter() { @@ -102,7 +102,10 @@ impl window::Window for Window { ) { ui.checkbox( &mut self.download_executable, - format!("Download latest version of {}", self.rgss_ver), + fl!( + "window_new_proj_with_exe_download_cb", + variant = self.rgss_ver.to_string() + ), ); } }); @@ -115,19 +118,20 @@ impl window::Window for Window { match res { Ok(_) => *open = false, Err(e) => { - state!() - .toasts - .error(format!("Failed to create project: {e}")); + state!().toasts.error(fl!( + "toast_error_creating_proj", + why = e.to_string() + )); self.project_promise = None; } } } if self.progress.zip_total.load(Ordering::Relaxed) != 0 { - ui.label(format!( - "Downloadind & Unzipping {}/{}", - self.progress.zip_current.load(Ordering::Relaxed) + 1, - self.progress.zip_total.load(Ordering::Relaxed) + ui.label(fl!( + "window_new_proj_dl_and_unzipping_label", + current = (self.progress.zip_current.load(Ordering::Relaxed) + 1), + total = self.progress.zip_total.load(Ordering::Relaxed) )); } @@ -145,7 +149,7 @@ impl window::Window for Window { }); } } else { - if ui.button("Ok").clicked() { + if ui.button(fl!("ok")).clicked() { let rgss_ver = self.rgss_ver; let config = config::project::Config { project_name: self.name.clone(), @@ -180,13 +184,15 @@ impl window::Window for Window { { Ok(mut c) => { if let Err(e) = c.wait() { - state.toasts.error(format!( - "Failed to initialize git repository {e}" + state.toasts.error(fl!( + "toast_error_init_git", + why = e.to_string() )); } } - Err(e) => state.toasts.error(format!( - "Failed to initialize git repository {e}" + Err(e) => state.toasts.error(fl!( + "toast_error_init_git", + why = e.to_string() )), } } @@ -202,7 +208,7 @@ impl window::Window for Window { result })); } - if ui.button("Cancel").clicked() { + if ui.button(fl!("cancel")).clicked() { *open = false; } } @@ -249,16 +255,29 @@ impl Window { progress.zip_current.store(index, Ordering::Relaxed); progress.total_progress.store(0, Ordering::Relaxed); - let mut response = - zip_response.map_err(|e| format!("Error downloading {rgss_ver}: {e}"))?; - - let bytes = response - .body_bytes() - .await - .map_err(|e| format!("Error getting response body for {rgss_ver}: {e}"))?; - - let mut archive = zip::ZipArchive::new(std::io::Cursor::new(bytes)) - .map_err(|e| format!("Failed to read zip archive for {rgss_ver}: {e}"))?; + let mut response = zip_response.map_err(|e| { + fl!( + "toast_error_downloading_rgss", + variant = rgss_ver.to_string(), + why = e.to_string() + ) + })?; + + let bytes = response.body_bytes().await.map_err(|e| { + fl!( + "toast_error_getting_body_resp", + variant = rgss_ver.to_string(), + why = e.to_string() + ) + })?; + + let mut archive = zip::ZipArchive::new(std::io::Cursor::new(bytes)).map_err(|e| { + fl!( + "toast_error_read_zip", + variant = rgss_ver.to_string(), + why = e.to_string() + ) + })?; progress .total_progress .store(archive.len(), Ordering::Relaxed); @@ -276,9 +295,10 @@ impl Window { let file_path = file_path .strip_prefix("mkxp-z_2.4.0/") .unwrap_or(&file_path); - let file_path = file_path - .to_str() - .ok_or(format!("Invalid file path {file_path:#?}"))?; + let file_path = file_path.to_str().ok_or(fl!( + "toast_error_invalid_file_path", + file_path = file_path.to_string_lossy() + ))?; if file_path.is_empty() || state @@ -290,19 +310,31 @@ impl Window { } if file.is_dir() { - state - .filesystem - .create_dir(file_path) - .map_err(|e| format!("Failed to create directory {file_path}: {e}"))?; + state.filesystem.create_dir(file_path).map_err(|e| { + fl!( + "toast_error_create_dir", + file_path = file_path, + why = e.to_string() + ) + })?; } else { let mut bytes = Vec::new(); file.read_to_end(&mut bytes) .map_err(|e| e.to_string()) - .map_err(|e| format!("Failed to read file data {file_path}: {e}"))?; - state - .filesystem - .write(file_path, bytes) - .map_err(|e| format!("Failed to save file data {file_path}: {e}"))?; + .map_err(|e| { + fl!( + "toast_error_reading_file_data", + file_path = file_path, + why = e + ) + })?; + state.filesystem.write(file_path, bytes).map_err(|e| { + fl!( + "toast_error_saving_file_data", + file_path = file_path, + why = e.to_string() + ) + })?; } } } diff --git a/src/windows/script_edit.rs b/src/windows/script_edit.rs index 3d637794..d8378ae0 100644 --- a/src/windows/script_edit.rs +++ b/src/windows/script_edit.rs @@ -41,8 +41,8 @@ impl window::Window for Window { fn name(&self) -> String { self.tabs .focused_name() - .map_or("Scripts".to_string(), |name| { - format!("Editing Script {name}") + .map_or(fl!("window_script_editor_fallback_title_label"), |name| { + fl!("window_script_editor_title_label", name = name) }) } @@ -69,12 +69,18 @@ impl window::Window for Window { let response = ui .text_edit_singleline(&mut script.name) .context_menu(|ui| { - if ui.button("Insert").clicked() { + if ui + .button(fl!("window_script_editor_insert_btn")) + .clicked() + { insert_index = Some(index); } ui.add_enabled_ui(scripts_len > 1, |ui| { - if ui.button("Delete").clicked() { + if ui + .button(fl!("window_script_editor_delete_btn")) + .clicked() + { del_index = Some(index); } }); @@ -90,7 +96,7 @@ impl window::Window for Window { scripts.insert( index, rpg::Script { - name: "New Script".to_string(), + name: fl!("window_script_editor_new_str"), script_text: String::new(), }, ); @@ -142,16 +148,16 @@ impl tab::Tab for ScriptTab { ui.horizontal(|ui| { let mut save_script = false; - if ui.button("Ok").clicked() { + if ui.button(fl!("ok")).clicked() { save_script = true; self.force_close = true; } - if ui.button("Cancel").clicked() { + if ui.button(fl!("cancel")).clicked() { self.force_close = true; } - if ui.button("Apply").clicked() { + if ui.button(fl!("apply")).clicked() { save_script = true; } diff --git a/src/windows/sound_test.rs b/src/windows/sound_test.rs index bc0edd3a..a3930f7a 100644 --- a/src/windows/sound_test.rs +++ b/src/windows/sound_test.rs @@ -22,7 +22,7 @@ // terms of the Steamworks API by Valve Corporation, the licensors of this // Program grant you additional permission to convey the resulting work. -use crate::prelude::*; +use crate::{fl, prelude::*}; /// A tab for a sound (be it BGM, ME, SE, etc) /// Optionally can be in 'picker' mode to pick a sound effect. @@ -60,7 +60,9 @@ impl SoundTab { .show_inside(ui, |ui| { ui.vertical(|ui| { ui.horizontal(|ui| { - if ui.button("Play").clicked() && !self.selected_track.as_str().is_empty() { + if ui.button(fl!("window_sound_test_play_btn")).clicked() + && !self.selected_track.as_str().is_empty() + { let path = format!("Audio/{}/{}", self.source, &self.selected_track); let pitch = self.pitch; let volume = self.volume; @@ -72,7 +74,7 @@ impl SoundTab { } } - if ui.button("Stop").clicked() { + if ui.button(fl!("window_sound_test_stop_btn")).clicked() { // Stop sound. state!().audio.stop(&self.source); } @@ -85,7 +87,7 @@ impl SoundTab { .add( egui::Slider::new(&mut self.volume, 0..=100) .orientation(egui::SliderOrientation::Vertical) - .text("Volume"), + .text(fl!("window_sound_test_volume_label")), ) .changed() { @@ -97,7 +99,7 @@ impl SoundTab { .add( egui::Slider::new(&mut self.pitch, 50..=150) .orientation(egui::SliderOrientation::Vertical) - .text("Pitch"), + .text(fl!("window_sound_test_pitch_label")), ) .changed() { @@ -107,8 +109,8 @@ impl SoundTab { if self.picker { ui.horizontal(|ui| { - if ui.button("Cancel").clicked() {} - if ui.button("Ok").clicked() {} + if ui.button(fl!("cancel")).clicked() {} + if ui.button(fl!("ok")).clicked() {} }); } }); @@ -184,31 +186,33 @@ impl super::window::Window for Window { } fn show(&mut self, ctx: &egui::Context, open: &mut bool) { - egui::Window::new("Sound Test").open(open).show(ctx, |ui| { - egui::TopBottomPanel::top("sound_test_selector").show_inside(ui, |ui| { - // Display the tab selector. - ui.horizontal_wrapped(|ui| { - for source in &self.sources { - if ui - .selectable_label( - source.source == self.selected_source, - source.source.to_string(), - ) - .clicked() - { - self.selected_source = source.source; + egui::Window::new(fl!("window_sound_test_title_label")) + .open(open) + .show(ctx, |ui| { + egui::TopBottomPanel::top("sound_test_selector").show_inside(ui, |ui| { + // Display the tab selector. + ui.horizontal_wrapped(|ui| { + for source in &self.sources { + if ui + .selectable_label( + source.source == self.selected_source, + source.source.to_string(), + ) + .clicked() + { + self.selected_source = source.source; + } } - } - }) - }); + }) + }); - // We should be finding something. The unwrap is safe here. - self.sources - .iter_mut() - .find(|t| t.source == self.selected_source) - .unwrap() - .ui(ui); - }); + // We should be finding something. The unwrap is safe here. + self.sources + .iter_mut() + .find(|t| t.source == self.selected_source) + .unwrap() + .ui(ui); + }); } // Technically we don't need the cache, but we do rely on the project being open. diff --git a/src/windows/window.rs b/src/windows/window.rs index d4e2c8ea..3b562aee 100644 --- a/src/windows/window.rs +++ b/src/windows/window.rs @@ -24,6 +24,8 @@ use parking_lot::Mutex; +use crate::fl; + /// A window management system to handle heap allocated windows /// /// Will deny any duplicated window titles and is not specialized like modals @@ -77,7 +79,7 @@ pub trait Window { /// Optionally used as the title of the window. fn name(&self) -> String { - "Untitled Window".to_string() + fl!("window_untitled_title") } /// Required to prevent duplication.