feat(locale): add Fluent translations
Default to the platform language with persisted overrides across native and web builds. Refs #630
This commit is contained in:
parent
e102887000
commit
b90b3e3ecf
26 changed files with 1581 additions and 112 deletions
403
Cargo.lock
generated
403
Cargo.lock
generated
|
|
@ -30,6 +30,8 @@ dependencies = [
|
|||
"fontdb",
|
||||
"getrandom 0.3.4",
|
||||
"glam",
|
||||
"i18n-embed",
|
||||
"i18n-embed-fl",
|
||||
"iced",
|
||||
"iced_aw",
|
||||
"iced_core",
|
||||
|
|
@ -45,6 +47,7 @@ dependencies = [
|
|||
"printpdf",
|
||||
"rayon",
|
||||
"rfd",
|
||||
"rust-embed",
|
||||
"rustc-hash 2.1.3",
|
||||
"semver",
|
||||
"serde",
|
||||
|
|
@ -116,7 +119,7 @@ checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0"
|
|||
dependencies = [
|
||||
"cfg-if",
|
||||
"cipher",
|
||||
"cpufeatures",
|
||||
"cpufeatures 0.2.17",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -371,6 +374,15 @@ dependencies = [
|
|||
"x11rb",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arc-swap"
|
||||
version = "1.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c049c0be4daef0b145cb3555416b3b8ef5b7888a38aea1a3a155801fe7b0810b"
|
||||
dependencies = [
|
||||
"rustversion",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "arg_enum_proc_macro"
|
||||
version = "0.3.4"
|
||||
|
|
@ -661,6 +673,15 @@ version = "0.22.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "72b3254f16251a8381aa12e40e3c4d2f0199f8c6508fbecb9d91f575e0fbb8c6"
|
||||
|
||||
[[package]]
|
||||
name = "basic-toml"
|
||||
version = "0.1.10"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ba62675e8242a4c4e806d12f11d136e626e6c8361d6b829310732241652a178a"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "bincode"
|
||||
version = "1.3.3"
|
||||
|
|
@ -760,6 +781,15 @@ dependencies = [
|
|||
"generic-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-buffer"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d2f6c7dbe95a6ed67ad9f18e57daf93a2f034c524b99fd2b76d18fdfeb6660aa"
|
||||
dependencies = [
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "block-padding"
|
||||
version = "0.3.3"
|
||||
|
|
@ -1002,7 +1032,7 @@ version = "0.4.4"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad"
|
||||
dependencies = [
|
||||
"crypto-common",
|
||||
"crypto-common 0.1.7",
|
||||
"inout",
|
||||
]
|
||||
|
||||
|
|
@ -1116,6 +1146,12 @@ dependencies = [
|
|||
"wasm-bindgen",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "const-oid"
|
||||
version = "0.10.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a6ef517f0926dd24a1582492c791b6a4818a4d94e789a334894aa15b0d12f55c"
|
||||
|
||||
[[package]]
|
||||
name = "convert_case"
|
||||
version = "0.4.0"
|
||||
|
|
@ -1238,6 +1274,15 @@ dependencies = [
|
|||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cpufeatures"
|
||||
version = "0.3.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8b2a41393f66f16b0823bb79094d54ac5fbd34ab292ddafb9a0456ac9f87d201"
|
||||
dependencies = [
|
||||
"libc",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crc32fast"
|
||||
version = "1.5.0"
|
||||
|
|
@ -1300,6 +1345,15 @@ dependencies = [
|
|||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "crypto-common"
|
||||
version = "0.2.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ce6e4c961d6cd6c9a86db418387425e8bdeaf05b3c8bc1411e6dca4c252f1453"
|
||||
dependencies = [
|
||||
"hybrid-array",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ctor"
|
||||
version = "0.10.1"
|
||||
|
|
@ -1391,8 +1445,19 @@ version = "0.10.7"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292"
|
||||
dependencies = [
|
||||
"block-buffer",
|
||||
"crypto-common",
|
||||
"block-buffer 0.10.4",
|
||||
"crypto-common 0.1.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "digest"
|
||||
version = "0.11.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f1dd6dbb5841937940781866fa1281a1ff7bd3bf827091440879f9994983d5c2"
|
||||
dependencies = [
|
||||
"block-buffer 0.12.1",
|
||||
"const-oid",
|
||||
"crypto-common 0.2.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -1413,6 +1478,17 @@ dependencies = [
|
|||
"objc2 0.6.4",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "displaydoc"
|
||||
version = "0.2.7"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c6232dd377dcc64799954cbd3a9bb882e9cdc1308ccd87b1c098f1fb2eaf82a8"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "dlib"
|
||||
version = "0.5.3"
|
||||
|
|
@ -1664,6 +1740,15 @@ dependencies = [
|
|||
"simd-adler32",
|
||||
]
|
||||
|
||||
[[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 = "find-msvc-tools"
|
||||
version = "0.1.9"
|
||||
|
|
@ -1698,6 +1783,51 @@ version = "1.0.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8bf7cc16383c4b8d58b9905a8509f02926ce3058053c056376248d958c9df1e8"
|
||||
|
||||
[[package]]
|
||||
name = "fluent"
|
||||
version = "0.17.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8137a6d5a2c50d6b0ebfcb9aaa91a28154e0a70605f112d30cb0cd4a78670477"
|
||||
dependencies = [
|
||||
"fluent-bundle",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluent-bundle"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "01203cb8918f5711e73891b347816d932046f95f54207710bda99beaeb423bf4"
|
||||
dependencies = [
|
||||
"fluent-langneg",
|
||||
"fluent-syntax",
|
||||
"intl-memoizer",
|
||||
"intl_pluralrules",
|
||||
"rustc-hash 2.1.3",
|
||||
"self_cell",
|
||||
"smallvec",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluent-langneg"
|
||||
version = "0.13.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7eebbe59450baee8282d71676f3bfed5689aeab00b27545e83e5f14b1195e8b0"
|
||||
dependencies = [
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "fluent-syntax"
|
||||
version = "0.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "54f0d287c53ffd184d04d8677f590f4ac5379785529e5e08b1c8083acdd5c198"
|
||||
dependencies = [
|
||||
"memchr 2.8.3",
|
||||
"thiserror 2.0.18",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "foldhash"
|
||||
version = "0.1.5"
|
||||
|
|
@ -2172,6 +2302,83 @@ version = "1.10.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6dbf3de79e51f3d586ab4cb9d5c3e2c14aa28ed23d180cf89b4df0454a69cc87"
|
||||
|
||||
[[package]]
|
||||
name = "hybrid-array"
|
||||
version = "0.4.14"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "707114b52a152fa7bdb290cd7cd5912d9467273b6d74e21b8d81aca1f8533f6b"
|
||||
dependencies = [
|
||||
"typenum",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "i18n-config"
|
||||
version = "0.4.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3e06b90c8a0d252e203c94344b21e35a30f3a3a85dc7db5af8f8df9f3e0c63ef"
|
||||
dependencies = [
|
||||
"basic-toml",
|
||||
"log",
|
||||
"serde",
|
||||
"serde_derive",
|
||||
"thiserror 1.0.69",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "i18n-embed"
|
||||
version = "0.16.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a217bbb075dcaefb292efa78897fc0678245ca67f265d12c351e42268fcb0305"
|
||||
dependencies = [
|
||||
"arc-swap",
|
||||
"fluent",
|
||||
"fluent-langneg",
|
||||
"fluent-syntax",
|
||||
"i18n-embed-impl",
|
||||
"intl-memoizer",
|
||||
"log",
|
||||
"parking_lot",
|
||||
"rust-embed",
|
||||
"sys-locale",
|
||||
"thiserror 1.0.69",
|
||||
"unic-langid",
|
||||
"walkdir",
|
||||
"web-sys",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "i18n-embed-fl"
|
||||
version = "0.10.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "602e6bd30c3db2749e13e38b363a3d98d9d41de1d8de7a79c31bb69e45b47cda"
|
||||
dependencies = [
|
||||
"find-crate",
|
||||
"fluent",
|
||||
"fluent-syntax",
|
||||
"i18n-config",
|
||||
"i18n-embed",
|
||||
"proc-macro-error3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"strsim",
|
||||
"syn 2.0.119",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "i18n-embed-impl"
|
||||
version = "0.8.4"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0f2cc0e0523d1fe6fc2c6f66e5038624ea8091b3e7748b5e8e0c84b1698db6c2"
|
||||
dependencies = [
|
||||
"find-crate",
|
||||
"i18n-config",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "iana-time-zone"
|
||||
version = "0.1.65"
|
||||
|
|
@ -2494,6 +2701,25 @@ dependencies = [
|
|||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "intl-memoizer"
|
||||
version = "0.5.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "310da2e345f5eb861e7a07ee182262e94975051db9e4223e909ba90f392f163f"
|
||||
dependencies = [
|
||||
"type-map",
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "intl_pluralrules"
|
||||
version = "7.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "078ea7b7c29a2b4df841a7f6ac8775ff6074020c6776d48491ce2268e068f972"
|
||||
dependencies = [
|
||||
"unic-langid",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "inventory"
|
||||
version = "0.3.24"
|
||||
|
|
@ -2872,7 +3098,7 @@ dependencies = [
|
|||
"nom_locate",
|
||||
"rand 0.9.5",
|
||||
"rangemap",
|
||||
"sha2",
|
||||
"sha2 0.10.9",
|
||||
"stringprep",
|
||||
"thiserror 2.0.18",
|
||||
"time",
|
||||
|
|
@ -2993,7 +3219,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "d89e7ee0cfbedfc4da3340218492196241d89eefb6dab27de5df917a6d2e78cf"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"digest",
|
||||
"digest 0.10.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -3029,6 +3255,22 @@ dependencies = [
|
|||
"autocfg",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "mime"
|
||||
version = "0.3.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6877bb514081ee2a7ff5ef9de3281f14a4dd4bceac4c09388074a6b5df8a139a"
|
||||
|
||||
[[package]]
|
||||
name = "mime_guess"
|
||||
version = "2.0.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f7c44f8e672c00fe5308fa235f821cb4198414e1c77935c1ab6948d3fd78550e"
|
||||
dependencies = [
|
||||
"mime",
|
||||
"unicase",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "minimal-lexical"
|
||||
version = "0.2.1"
|
||||
|
|
@ -4127,6 +4369,28 @@ dependencies = [
|
|||
"version_check",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error-attr3"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0084e6206a967a2dad822180626b2f6b07a3b379325e8f1ec0438e33a469ba7"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro-error3"
|
||||
version = "3.1.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cf066225f2373bc711684792b69bdeac0356019b007e721090c24d92d5d5a50"
|
||||
dependencies = [
|
||||
"proc-macro-error-attr3",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 3.0.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "proc-macro2"
|
||||
version = "1.0.106"
|
||||
|
|
@ -4687,6 +4951,41 @@ version = "0.20.0"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "6c20b6793b5c2fa6553b250154b78d6d0db37e72700ae35fad9387a46f487c97"
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed"
|
||||
version = "8.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e9e7760e252aaba7b09f4be00e36476cf585bdb68a53552ac954cdf504ab4bc9"
|
||||
dependencies = [
|
||||
"rust-embed-impl",
|
||||
"rust-embed-utils",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-impl"
|
||||
version = "8.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "3bcfc4d6f53af43755f7a723e4b6b8794fcce052a178dd8c6c1dadc5f5343097"
|
||||
dependencies = [
|
||||
"mime_guess",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"rust-embed-utils",
|
||||
"syn 2.0.119",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rust-embed-utils"
|
||||
version = "8.12.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "42ffa149f6aa81b58a5b3011d01a857c4ed12c7a732d2c51947a4c7c692185f0"
|
||||
dependencies = [
|
||||
"sha2 0.11.0",
|
||||
"walkdir",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
version = "1.1.0"
|
||||
|
|
@ -5013,8 +5312,19 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||
checksum = "a7507d819769d01a365ab707794a4084392c824f54a7a6a7862f8c3d0892b283"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures",
|
||||
"digest",
|
||||
"cpufeatures 0.2.17",
|
||||
"digest 0.10.7",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sha2"
|
||||
version = "0.11.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "446ba717509524cb3f22f17ecc096f10f4822d76ab5c0b9822c5f9c284e825f4"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"cpufeatures 0.3.0",
|
||||
"digest 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
|
|
@ -5354,6 +5664,17 @@ dependencies = [
|
|||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "syn"
|
||||
version = "3.0.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "53e9bae58849f64dfa4f5d5ae372c8341f7305f82a3868709269343628b659a3"
|
||||
dependencies = [
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"unicode-ident",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "sys-locale"
|
||||
version = "0.3.2"
|
||||
|
|
@ -5514,6 +5835,17 @@ dependencies = [
|
|||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinystr"
|
||||
version = "0.8.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c8323304221c2a851516f22236c5722a72eaa19749016521d6dff0824447d96d"
|
||||
dependencies = [
|
||||
"displaydoc",
|
||||
"serde_core",
|
||||
"zerovec",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "tinyvec"
|
||||
version = "1.12.0"
|
||||
|
|
@ -5529,6 +5861,15 @@ version = "0.1.1"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "0.5.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234"
|
||||
dependencies = [
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "toml"
|
||||
version = "1.1.3+spec-1.1.0"
|
||||
|
|
@ -5800,6 +6141,15 @@ dependencies = [
|
|||
"core_maths",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "type-map"
|
||||
version = "0.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb30dbbd9036155e74adad6812e9898d03ec374946234fbcebd5dfc7b9187b90"
|
||||
dependencies = [
|
||||
"rustc-hash 2.1.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "typenum"
|
||||
version = "1.20.1"
|
||||
|
|
@ -5823,6 +6173,25 @@ dependencies = [
|
|||
"windows-sys 0.61.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unic-langid"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "a28ba52c9b05311f4f6e62d5d9d46f094bd6e84cb8df7b3ef952748d752a7d05"
|
||||
dependencies = [
|
||||
"unic-langid-impl",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unic-langid-impl"
|
||||
version = "0.9.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "dce1bf08044d4b7a94028c93786f8566047edc11110595914de93362559bc658"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"tinystr",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "unicase"
|
||||
version = "2.9.0"
|
||||
|
|
@ -6885,7 +7254,7 @@ version = "0.1.31"
|
|||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0986a8b1d586b7d3e4fe3d9ea39fb451ae22869dcea4aa109d287a374d866087"
|
||||
dependencies = [
|
||||
"toml",
|
||||
"toml 1.1.3+spec-1.1.0",
|
||||
"version_check",
|
||||
]
|
||||
|
||||
|
|
@ -7099,12 +7468,28 @@ dependencies = [
|
|||
"syn 2.0.119",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zerofrom"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0ec05a11813ea801ff6d75110ad09cd0824ddba17dfe17128ea0d5f68e6c5272"
|
||||
|
||||
[[package]]
|
||||
name = "zeroize"
|
||||
version = "1.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e13c156562582aa81c60cb29407084cdb54c4164760106ab78e6c5b0858cf64e"
|
||||
|
||||
[[package]]
|
||||
name = "zerovec"
|
||||
version = "0.11.6"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "90f911cbc359ab6af17377d242225f4d75119aec87ea711a880987b18cd7b239"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"zerofrom",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "zmij"
|
||||
version = "1.0.23"
|
||||
|
|
|
|||
|
|
@ -39,6 +39,9 @@ acadrust = { version = "0.4", features = ["serde"] }
|
|||
dwg-thumbnailer = { path = "crates/dwg-thumbnailer" }
|
||||
flate2 = "1"
|
||||
image = { version = "0.25", default-features = false, features = ["png", "jpeg", "bmp", "tiff"] }
|
||||
i18n-embed = { version = "0.16", features = ["fluent-system"] }
|
||||
i18n-embed-fl = "0.10"
|
||||
rust-embed = "8"
|
||||
inventory = "0.3"
|
||||
truck-shapeops = { version = "0.4", optional = true }
|
||||
rustc-hash = "2"
|
||||
|
|
@ -64,6 +67,7 @@ iced_widget = { git = "https://github.com/iced-rs/iced.git", rev = "23604ff22ab0
|
|||
|
||||
[target.'cfg(not(target_arch = "wasm32"))'.dependencies]
|
||||
ocs_plugin_api = { path = "crates/ocs_plugin_api", features = ["host"] }
|
||||
i18n-embed = { version = "0.16", features = ["desktop-requester"] }
|
||||
rayon = "1"
|
||||
open = "5"
|
||||
printpdf = { version = "0.9.1", default-features = false }
|
||||
|
|
@ -71,6 +75,7 @@ ureq = { version = "3", default-features = false, features = ["rustls", "platfor
|
|||
|
||||
[target.'cfg(target_arch = "wasm32")'.dependencies]
|
||||
ocs_plugin_api = { path = "crates/ocs_plugin_api" }
|
||||
i18n-embed = { version = "0.16", features = ["web-sys-requester"] }
|
||||
console_error_panic_hook = "0.1"
|
||||
log = "0.4"
|
||||
getrandom = { version = "0.3", features = ["wasm_js"] }
|
||||
|
|
|
|||
5
i18n.toml
Normal file
5
i18n.toml
Normal file
|
|
@ -0,0 +1,5 @@
|
|||
fallback_language = "en-US"
|
||||
|
||||
[fluent]
|
||||
assets_dir = "locales"
|
||||
domain = "opencadstudio"
|
||||
113
locales/de-DE/opencadstudio.ftl
Normal file
113
locales/de-DE/opencadstudio.ftl
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
language-system = Systemsprache
|
||||
language-english = English
|
||||
language-turkish = Türkçe
|
||||
language-dutch = Nederlands
|
||||
language-french = Français
|
||||
language-german = Deutsch
|
||||
language-hindi = हिन्दी
|
||||
language-russian = Русский
|
||||
language-chinese-simplified = 简体中文
|
||||
|
||||
action-close = Schließen
|
||||
action-options = Optionen
|
||||
action-plugins = Plug-ins
|
||||
|
||||
ribbon-tab-draw = Zeichnen
|
||||
ribbon-tab-annotate = Beschriften
|
||||
ribbon-tab-insert = Einfügen
|
||||
ribbon-tab-model = Modell
|
||||
ribbon-tab-layout = Layout
|
||||
ribbon-tab-manage = Verwalten
|
||||
ribbon-tab-view = Ansicht
|
||||
|
||||
options-language-section = Sprache
|
||||
options-language-label = Oberflächensprache:
|
||||
options-open-save-section = Öffnen und Speichern
|
||||
options-default-save-format-label = Standardspeicherformat:
|
||||
options-default-save-format-help = Wird beim ersten Speichern einer neuen Zeichnung verwendet. Vorhandene Zeichnungen behalten Dateityp und Version bei.
|
||||
options-theme-section = Design
|
||||
options-theme-label = Anwendungsdesign:
|
||||
options-theme-help = Das Ändern einer Grundfarbe aktiviert das benutzerdefinierte Design. Alle Komponentenfarben werden aus diesen sechs Farben erzeugt.
|
||||
options-color-background = Hintergrund
|
||||
options-color-text = Text
|
||||
options-color-primary = Primär
|
||||
options-color-success = Erfolg
|
||||
options-color-warning = Warnung
|
||||
options-color-danger = Gefahr
|
||||
|
||||
command-line-ready = Open CAD Studio ist bereit.
|
||||
command-line-hint = Geben Sie einen Befehl ein oder verwenden Sie das Menüband. Öffnen Sie OBJ über die Registerkarte Einfügen.
|
||||
command-line-label = Befehl:
|
||||
command-line-literal-spaces = Wörtliche Leerzeichen: Das Leerzeichen bleibt in der Zeile, statt den Befehl auszuführen. Bleibt bis zum Ausschalten aktiv.
|
||||
|
||||
start-new-drawing = Neue Zeichnung
|
||||
start-open-file = Datei öffnen…
|
||||
start-donate = Spenden
|
||||
start-send-feedback = Feedback senden
|
||||
start-sponsors = Sponsoren
|
||||
start-tutorials = Lernprogramme
|
||||
start-loading-videos = Videos werden geladen…
|
||||
start-videos-online = Videos werden aus dem Internet geladen.
|
||||
start-open-playlist = Wiedergabeliste auf YouTube öffnen
|
||||
start-discussions = Diskussionen
|
||||
start-pinned = Angeheftet
|
||||
start-loading-discussions = Diskussionen werden geladen…
|
||||
start-discussions-online = Diskussionen werden von GitHub geladen.
|
||||
start-open-discussions = Diskussionen auf GitHub öffnen
|
||||
start-supporters = Unterstützer
|
||||
start-support-on-patreon = Auf Patreon unterstützen
|
||||
start-recent-files = Zuletzt verwendete Dateien
|
||||
start-videos = Videos
|
||||
start-welcome = Willkommen
|
||||
start-recent-documents = Zuletzt verwendete Dokumente
|
||||
start-no-recent-files = Geöffnete Dateien werden hier angezeigt.
|
||||
start-browser-storage = Browserspeicher
|
||||
start-keep-recent-files = Zuletzt verwendete Dateien behalten
|
||||
|
||||
modal-about = Info
|
||||
modal-keyboard-shortcuts = Tastenkombinationen
|
||||
modal-command-aliases = Befehlsaliase
|
||||
modal-find-replace = Suchen und Ersetzen
|
||||
modal-plugin-manager = Plug-in-Manager
|
||||
modal-update-available = Aktualisierung verfügbar
|
||||
modal-layer-manager = Layer-Manager
|
||||
modal-layer-state-manager = Layerstatus-Manager
|
||||
modal-edit-layer-state = Layerstatus bearbeiten
|
||||
modal-plot = Plotten
|
||||
modal-layout-manager = Layout-Manager
|
||||
modal-scale-manager = Maßstabs-Manager
|
||||
modal-annotation-object-scale = Maßstab des Beschriftungsobjekts
|
||||
modal-plot-style-editor = Plotstileditor
|
||||
modal-text-style-manager = Textstil-Manager
|
||||
modal-multiline-style-manager = Mehrfachlinienstil-Manager
|
||||
modal-table-style-manager = Tabellenstil-Manager
|
||||
modal-multileader-style-manager = Multi-Führungslinienstil-Manager
|
||||
modal-dimension-style-manager = Bemaßungsstil-Manager
|
||||
modal-default-application = Standardanwendung
|
||||
modal-save-warning = Speicherwarnung
|
||||
modal-unable-save = Zeichnung kann nicht gespeichert werden
|
||||
modal-drawing-changed = Zeichnung auf dem Datenträger geändert
|
||||
modal-delete-layer = Layer löschen
|
||||
modal-unsaved-changes = Nicht gespeicherte Änderungen
|
||||
modal-point-style = Punktstil
|
||||
modal-attribute-editor = Attribut-Editor
|
||||
modal-save-drawing-as = Zeichnung speichern unter
|
||||
|
||||
command-move-base =
|
||||
MOVE Basispunkt angeben [{ $count ->
|
||||
[one] { $count } Objekt
|
||||
*[other] { $count } Objekte
|
||||
}]:
|
||||
command-move-target = MOVE Zielpunkt angeben [Basis { $x },{ $y }]:
|
||||
command-copy-array-count = COPY Anzahl der Elemente im Array eingeben:
|
||||
command-copy-base =
|
||||
COPY Basispunkt angeben [{ $count ->
|
||||
[one] { $count } Objekt
|
||||
*[other] { $count } Objekte
|
||||
}]:
|
||||
command-copy-array-target = COPY Zweiten Punkt für das Array mit { $count } Elementen angeben [Basis { $x },{ $y }]:
|
||||
command-copy-target =
|
||||
COPY Zielpunkt angeben [{ $count ->
|
||||
[one] bisher { $count } Kopie
|
||||
*[other] bisher { $count } Kopien
|
||||
} | Array | Eingabe=fertig | Basis { $x },{ $y }]:
|
||||
113
locales/en-US/opencadstudio.ftl
Normal file
113
locales/en-US/opencadstudio.ftl
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
language-system = System language
|
||||
language-english = English
|
||||
language-turkish = Türkçe
|
||||
language-dutch = Nederlands
|
||||
language-french = Français
|
||||
language-german = Deutsch
|
||||
language-hindi = हिन्दी
|
||||
language-russian = Русский
|
||||
language-chinese-simplified = Simplified Chinese
|
||||
|
||||
action-close = Close
|
||||
action-options = Options
|
||||
action-plugins = Plugins
|
||||
|
||||
ribbon-tab-draw = Draw
|
||||
ribbon-tab-annotate = Annotate
|
||||
ribbon-tab-insert = Insert
|
||||
ribbon-tab-model = Model
|
||||
ribbon-tab-layout = Layout
|
||||
ribbon-tab-manage = Manage
|
||||
ribbon-tab-view = View
|
||||
|
||||
options-language-section = Language
|
||||
options-language-label = Interface language:
|
||||
options-open-save-section = Open and Save
|
||||
options-default-save-format-label = Default save format:
|
||||
options-default-save-format-help = Used for the first save of a new drawing. Existing drawings keep their file type and version.
|
||||
options-theme-section = Theme
|
||||
options-theme-label = Application theme:
|
||||
options-theme-help = Changing a base colour switches to Custom. The theme generates every component shade from these six colours.
|
||||
options-color-background = Background
|
||||
options-color-text = Text
|
||||
options-color-primary = Primary
|
||||
options-color-success = Success
|
||||
options-color-warning = Warning
|
||||
options-color-danger = Danger
|
||||
|
||||
command-line-ready = Open CAD Studio ready.
|
||||
command-line-hint = Type a command or use the ribbon. Open OBJ from the Insert tab.
|
||||
command-line-label = Command:
|
||||
command-line-literal-spaces = Literal spaces: Space stays in the line instead of running the command. Stays on until toggled off.
|
||||
|
||||
start-new-drawing = New Drawing
|
||||
start-open-file = Open File…
|
||||
start-donate = Donate
|
||||
start-send-feedback = Send Feedback
|
||||
start-sponsors = Sponsors
|
||||
start-tutorials = Tutorials
|
||||
start-loading-videos = Loading videos…
|
||||
start-videos-online = Videos load from the internet.
|
||||
start-open-playlist = Open playlist on YouTube
|
||||
start-discussions = Discussions
|
||||
start-pinned = Pinned
|
||||
start-loading-discussions = Loading discussions…
|
||||
start-discussions-online = Discussions load from GitHub.
|
||||
start-open-discussions = Open Discussions on GitHub
|
||||
start-supporters = Supporters
|
||||
start-support-on-patreon = Support on Patreon
|
||||
start-recent-files = Recent Files
|
||||
start-videos = Videos
|
||||
start-welcome = Welcome
|
||||
start-recent-documents = Recent Documents
|
||||
start-no-recent-files = Files you open will show up here.
|
||||
start-browser-storage = Browser storage
|
||||
start-keep-recent-files = Keep recent files
|
||||
|
||||
modal-about = About
|
||||
modal-keyboard-shortcuts = Keyboard Shortcuts
|
||||
modal-command-aliases = Command Aliases
|
||||
modal-find-replace = Find and Replace
|
||||
modal-plugin-manager = Plugin Manager
|
||||
modal-update-available = Update Available
|
||||
modal-layer-manager = Layer Manager
|
||||
modal-layer-state-manager = Layer State Manager
|
||||
modal-edit-layer-state = Edit Layer State
|
||||
modal-plot = Plot
|
||||
modal-layout-manager = Layout Manager
|
||||
modal-scale-manager = Scale Manager
|
||||
modal-annotation-object-scale = Annotation Object Scale
|
||||
modal-plot-style-editor = Plot Style Editor
|
||||
modal-text-style-manager = Text Style Manager
|
||||
modal-multiline-style-manager = Multiline Style Manager
|
||||
modal-table-style-manager = Table Style Manager
|
||||
modal-multileader-style-manager = Multileader Style Manager
|
||||
modal-dimension-style-manager = Dimension Style Manager
|
||||
modal-default-application = Default Application
|
||||
modal-save-warning = Save Warning
|
||||
modal-unable-save = Unable to Save Drawing
|
||||
modal-drawing-changed = Drawing Changed on Disk
|
||||
modal-delete-layer = Delete Layer
|
||||
modal-unsaved-changes = Unsaved Changes
|
||||
modal-point-style = Point Style
|
||||
modal-attribute-editor = Attribute Editor
|
||||
modal-save-drawing-as = Save Drawing As
|
||||
|
||||
command-move-base =
|
||||
MOVE Specify base point [{ $count ->
|
||||
[one] { $count } object
|
||||
*[other] { $count } objects
|
||||
}]:
|
||||
command-move-target = MOVE Specify destination [base { $x },{ $y }]:
|
||||
command-copy-array-count = COPY Enter number of items to array:
|
||||
command-copy-base =
|
||||
COPY Specify base point [{ $count ->
|
||||
[one] { $count } object
|
||||
*[other] { $count } objects
|
||||
}]:
|
||||
command-copy-array-target = COPY Specify second point for { $count }-item array [base { $x },{ $y }]:
|
||||
command-copy-target =
|
||||
COPY Specify destination [{ $count ->
|
||||
[one] { $count } copy so far
|
||||
*[other] { $count } copies so far
|
||||
} | Array | Enter=done | base { $x },{ $y }]:
|
||||
113
locales/fr-FR/opencadstudio.ftl
Normal file
113
locales/fr-FR/opencadstudio.ftl
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
language-system = Langue du système
|
||||
language-english = English
|
||||
language-turkish = Türkçe
|
||||
language-dutch = Nederlands
|
||||
language-french = Français
|
||||
language-german = Deutsch
|
||||
language-hindi = हिन्दी
|
||||
language-russian = Русский
|
||||
language-chinese-simplified = 简体中文
|
||||
|
||||
action-close = Fermer
|
||||
action-options = Options
|
||||
action-plugins = Extensions
|
||||
|
||||
ribbon-tab-draw = Dessin
|
||||
ribbon-tab-annotate = Annoter
|
||||
ribbon-tab-insert = Insérer
|
||||
ribbon-tab-model = Modèle
|
||||
ribbon-tab-layout = Présentation
|
||||
ribbon-tab-manage = Gérer
|
||||
ribbon-tab-view = Affichage
|
||||
|
||||
options-language-section = Langue
|
||||
options-language-label = Langue de l'interface :
|
||||
options-open-save-section = Ouvrir et enregistrer
|
||||
options-default-save-format-label = Format d'enregistrement par défaut :
|
||||
options-default-save-format-help = Utilisé lors du premier enregistrement d'un nouveau dessin. Les dessins existants conservent leur type de fichier et leur version.
|
||||
options-theme-section = Thème
|
||||
options-theme-label = Thème de l'application :
|
||||
options-theme-help = La modification d'une couleur de base active le thème personnalisé. Le thème génère toutes les nuances des composants à partir de ces six couleurs.
|
||||
options-color-background = Arrière-plan
|
||||
options-color-text = Texte
|
||||
options-color-primary = Principale
|
||||
options-color-success = Succès
|
||||
options-color-warning = Avertissement
|
||||
options-color-danger = Danger
|
||||
|
||||
command-line-ready = Open CAD Studio est prêt.
|
||||
command-line-hint = Saisissez une commande ou utilisez le ruban. Ouvrez un fichier OBJ depuis l'onglet Insérer.
|
||||
command-line-label = Commande :
|
||||
command-line-literal-spaces = Espaces littéraux : l'espace reste dans la ligne au lieu d'exécuter la commande. Ce mode reste actif jusqu'à sa désactivation.
|
||||
|
||||
start-new-drawing = Nouveau dessin
|
||||
start-open-file = Ouvrir un fichier…
|
||||
start-donate = Faire un don
|
||||
start-send-feedback = Envoyer des commentaires
|
||||
start-sponsors = Sponsors
|
||||
start-tutorials = Tutoriels
|
||||
start-loading-videos = Chargement des vidéos…
|
||||
start-videos-online = Les vidéos sont chargées depuis Internet.
|
||||
start-open-playlist = Ouvrir la playlist sur YouTube
|
||||
start-discussions = Discussions
|
||||
start-pinned = Épinglé
|
||||
start-loading-discussions = Chargement des discussions…
|
||||
start-discussions-online = Les discussions sont chargées depuis GitHub.
|
||||
start-open-discussions = Ouvrir les discussions sur GitHub
|
||||
start-supporters = Contributeurs
|
||||
start-support-on-patreon = Soutenir sur Patreon
|
||||
start-recent-files = Fichiers récents
|
||||
start-videos = Vidéos
|
||||
start-welcome = Bienvenue
|
||||
start-recent-documents = Documents récents
|
||||
start-no-recent-files = Les fichiers que vous ouvrez apparaîtront ici.
|
||||
start-browser-storage = Stockage du navigateur
|
||||
start-keep-recent-files = Conserver les fichiers récents
|
||||
|
||||
modal-about = À propos
|
||||
modal-keyboard-shortcuts = Raccourcis clavier
|
||||
modal-command-aliases = Alias de commandes
|
||||
modal-find-replace = Rechercher et remplacer
|
||||
modal-plugin-manager = Gestionnaire d'extensions
|
||||
modal-update-available = Mise à jour disponible
|
||||
modal-layer-manager = Gestionnaire de calques
|
||||
modal-layer-state-manager = Gestionnaire d'états de calque
|
||||
modal-edit-layer-state = Modifier l'état du calque
|
||||
modal-plot = Tracer
|
||||
modal-layout-manager = Gestionnaire de présentations
|
||||
modal-scale-manager = Gestionnaire d'échelles
|
||||
modal-annotation-object-scale = Échelle de l'objet annotatif
|
||||
modal-plot-style-editor = Éditeur de styles de tracé
|
||||
modal-text-style-manager = Gestionnaire de styles de texte
|
||||
modal-multiline-style-manager = Gestionnaire de styles de multilignes
|
||||
modal-table-style-manager = Gestionnaire de styles de tableau
|
||||
modal-multileader-style-manager = Gestionnaire de styles de lignes de repère multiples
|
||||
modal-dimension-style-manager = Gestionnaire de styles de cote
|
||||
modal-default-application = Application par défaut
|
||||
modal-save-warning = Avertissement d'enregistrement
|
||||
modal-unable-save = Impossible d'enregistrer le dessin
|
||||
modal-drawing-changed = Dessin modifié sur le disque
|
||||
modal-delete-layer = Supprimer le calque
|
||||
modal-unsaved-changes = Modifications non enregistrées
|
||||
modal-point-style = Style de point
|
||||
modal-attribute-editor = Éditeur d'attributs
|
||||
modal-save-drawing-as = Enregistrer le dessin sous
|
||||
|
||||
command-move-base =
|
||||
MOVE Spécifiez le point de base [{ $count ->
|
||||
[one] { $count } objet
|
||||
*[other] { $count } objets
|
||||
}] :
|
||||
command-move-target = MOVE Spécifiez la destination [base { $x },{ $y }] :
|
||||
command-copy-array-count = COPY Saisissez le nombre d'éléments du réseau :
|
||||
command-copy-base =
|
||||
COPY Spécifiez le point de base [{ $count ->
|
||||
[one] { $count } objet
|
||||
*[other] { $count } objets
|
||||
}] :
|
||||
command-copy-array-target = COPY Spécifiez le second point du réseau de { $count } éléments [base { $x },{ $y }] :
|
||||
command-copy-target =
|
||||
COPY Spécifiez la destination [{ $count ->
|
||||
[one] { $count } copie jusqu'ici
|
||||
*[other] { $count } copies jusqu'ici
|
||||
} | Réseau | Entrée=terminer | base { $x },{ $y }] :
|
||||
101
locales/hi-IN/opencadstudio.ftl
Normal file
101
locales/hi-IN/opencadstudio.ftl
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
language-system = सिस्टम भाषा
|
||||
language-english = English
|
||||
language-turkish = Türkçe
|
||||
language-dutch = Nederlands
|
||||
language-french = Français
|
||||
language-german = Deutsch
|
||||
language-hindi = हिन्दी
|
||||
language-russian = Русский
|
||||
language-chinese-simplified = 简体中文
|
||||
|
||||
action-close = बंद करें
|
||||
action-options = विकल्प
|
||||
action-plugins = प्लग-इन
|
||||
|
||||
ribbon-tab-draw = ड्रॉ
|
||||
ribbon-tab-annotate = एनोटेट
|
||||
ribbon-tab-insert = इन्सर्ट
|
||||
ribbon-tab-model = मॉडल
|
||||
ribbon-tab-layout = लेआउट
|
||||
ribbon-tab-manage = प्रबंधित करें
|
||||
ribbon-tab-view = दृश्य
|
||||
|
||||
options-language-section = भाषा
|
||||
options-language-label = इंटरफ़ेस भाषा:
|
||||
options-open-save-section = खोलना और सहेजना
|
||||
options-default-save-format-label = डिफ़ॉल्ट सहेजने का प्रारूप:
|
||||
options-default-save-format-help = नई ड्रॉइंग को पहली बार सहेजते समय उपयोग होता है। मौजूदा ड्रॉइंग अपना फ़ाइल प्रकार और संस्करण बनाए रखती हैं।
|
||||
options-theme-section = थीम
|
||||
options-theme-label = अनुप्रयोग थीम:
|
||||
options-theme-help = किसी मूल रंग को बदलने पर कस्टम थीम सक्रिय हो जाती है। थीम इन छह रंगों से सभी घटक शेड बनाती है।
|
||||
options-color-background = पृष्ठभूमि
|
||||
options-color-text = पाठ
|
||||
options-color-primary = प्राथमिक
|
||||
options-color-success = सफलता
|
||||
options-color-warning = चेतावनी
|
||||
options-color-danger = खतरा
|
||||
|
||||
command-line-ready = Open CAD Studio तैयार है।
|
||||
command-line-hint = कोई कमांड लिखें या रिबन का उपयोग करें। OBJ को इन्सर्ट टैब से खोलें।
|
||||
command-line-label = कमांड:
|
||||
command-line-literal-spaces = वास्तविक स्पेस: स्पेस कमांड चलाने के बजाय पंक्ति में रहता है। दोबारा बंद करने तक यह चालू रहता है।
|
||||
|
||||
start-new-drawing = नई ड्रॉइंग
|
||||
start-open-file = फ़ाइल खोलें…
|
||||
start-donate = दान करें
|
||||
start-send-feedback = प्रतिक्रिया भेजें
|
||||
start-sponsors = प्रायोजक
|
||||
start-tutorials = ट्यूटोरियल
|
||||
start-loading-videos = वीडियो लोड हो रहे हैं…
|
||||
start-videos-online = वीडियो इंटरनेट से लोड होते हैं।
|
||||
start-open-playlist = YouTube पर प्लेलिस्ट खोलें
|
||||
start-discussions = चर्चाएँ
|
||||
start-pinned = पिन किया गया
|
||||
start-loading-discussions = चर्चाएँ लोड हो रही हैं…
|
||||
start-discussions-online = चर्चाएँ GitHub से लोड होती हैं।
|
||||
start-open-discussions = GitHub पर चर्चाएँ खोलें
|
||||
start-supporters = समर्थक
|
||||
start-support-on-patreon = Patreon पर समर्थन करें
|
||||
start-recent-files = हाल की फ़ाइलें
|
||||
start-videos = वीडियो
|
||||
start-welcome = स्वागत है
|
||||
start-recent-documents = हाल के दस्तावेज़
|
||||
start-no-recent-files = आपके द्वारा खोली गई फ़ाइलें यहाँ दिखाई देंगी।
|
||||
start-browser-storage = ब्राउज़र संग्रहण
|
||||
start-keep-recent-files = हाल की फ़ाइलें रखें
|
||||
|
||||
modal-about = परिचय
|
||||
modal-keyboard-shortcuts = कीबोर्ड शॉर्टकट
|
||||
modal-command-aliases = कमांड उपनाम
|
||||
modal-find-replace = खोजें और बदलें
|
||||
modal-plugin-manager = प्लग-इन प्रबंधक
|
||||
modal-update-available = अपडेट उपलब्ध है
|
||||
modal-layer-manager = लेयर प्रबंधक
|
||||
modal-layer-state-manager = लेयर स्थिति प्रबंधक
|
||||
modal-edit-layer-state = लेयर स्थिति संपादित करें
|
||||
modal-plot = प्लॉट
|
||||
modal-layout-manager = लेआउट प्रबंधक
|
||||
modal-scale-manager = स्केल प्रबंधक
|
||||
modal-annotation-object-scale = एनोटेशन ऑब्जेक्ट स्केल
|
||||
modal-plot-style-editor = प्लॉट शैली संपादक
|
||||
modal-text-style-manager = टेक्स्ट शैली प्रबंधक
|
||||
modal-multiline-style-manager = मल्टीलाइन शैली प्रबंधक
|
||||
modal-table-style-manager = तालिका शैली प्रबंधक
|
||||
modal-multileader-style-manager = मल्टीलीडर शैली प्रबंधक
|
||||
modal-dimension-style-manager = डाइमेंशन शैली प्रबंधक
|
||||
modal-default-application = डिफ़ॉल्ट अनुप्रयोग
|
||||
modal-save-warning = सहेजने की चेतावनी
|
||||
modal-unable-save = ड्रॉइंग सहेजी नहीं जा सकती
|
||||
modal-drawing-changed = डिस्क पर ड्रॉइंग बदल गई
|
||||
modal-delete-layer = लेयर हटाएँ
|
||||
modal-unsaved-changes = न सहेजे गए बदलाव
|
||||
modal-point-style = बिंदु शैली
|
||||
modal-attribute-editor = विशेषता संपादक
|
||||
modal-save-drawing-as = ड्रॉइंग इस रूप में सहेजें
|
||||
|
||||
command-move-base = MOVE आधार बिंदु निर्दिष्ट करें [{ $count } ऑब्जेक्ट]:
|
||||
command-move-target = MOVE गंतव्य निर्दिष्ट करें [आधार { $x },{ $y }]:
|
||||
command-copy-array-count = COPY ऐरे में आइटमों की संख्या दर्ज करें:
|
||||
command-copy-base = COPY आधार बिंदु निर्दिष्ट करें [{ $count } ऑब्जेक्ट]:
|
||||
command-copy-array-target = COPY { $count }-आइटम ऐरे के लिए दूसरा बिंदु निर्दिष्ट करें [आधार { $x },{ $y }]:
|
||||
command-copy-target = COPY गंतव्य निर्दिष्ट करें [अब तक { $count } प्रतियाँ | ऐरे | Enter=पूर्ण | आधार { $x },{ $y }]:
|
||||
113
locales/nl-NL/opencadstudio.ftl
Normal file
113
locales/nl-NL/opencadstudio.ftl
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
language-system = Systeemtaal
|
||||
language-english = English
|
||||
language-turkish = Türkçe
|
||||
language-dutch = Nederlands
|
||||
language-french = Français
|
||||
language-german = Deutsch
|
||||
language-hindi = हिन्दी
|
||||
language-russian = Русский
|
||||
language-chinese-simplified = 简体中文
|
||||
|
||||
action-close = Sluiten
|
||||
action-options = Opties
|
||||
action-plugins = Plug-ins
|
||||
|
||||
ribbon-tab-draw = Tekenen
|
||||
ribbon-tab-annotate = Annoteren
|
||||
ribbon-tab-insert = Invoegen
|
||||
ribbon-tab-model = Model
|
||||
ribbon-tab-layout = Lay-out
|
||||
ribbon-tab-manage = Beheren
|
||||
ribbon-tab-view = Beeld
|
||||
|
||||
options-language-section = Taal
|
||||
options-language-label = Interfacetaal:
|
||||
options-open-save-section = Openen en opslaan
|
||||
options-default-save-format-label = Standaard opslagformaat:
|
||||
options-default-save-format-help = Wordt gebruikt wanneer een nieuwe tekening voor het eerst wordt opgeslagen. Bestaande tekeningen behouden hun bestandstype en versie.
|
||||
options-theme-section = Thema
|
||||
options-theme-label = Toepassingsthema:
|
||||
options-theme-help = Als u een basiskleur wijzigt, wordt het aangepaste thema geactiveerd. Het thema maakt alle componenttinten op basis van deze zes kleuren.
|
||||
options-color-background = Achtergrond
|
||||
options-color-text = Tekst
|
||||
options-color-primary = Primair
|
||||
options-color-success = Geslaagd
|
||||
options-color-warning = Waarschuwing
|
||||
options-color-danger = Gevaar
|
||||
|
||||
command-line-ready = Open CAD Studio is gereed.
|
||||
command-line-hint = Typ een opdracht of gebruik het lint. Open OBJ via het tabblad Invoegen.
|
||||
command-line-label = Opdracht:
|
||||
command-line-literal-spaces = Letterlijke spaties: een spatie blijft in de regel staan in plaats van de opdracht uit te voeren. Blijft actief tot u dit uitschakelt.
|
||||
|
||||
start-new-drawing = Nieuwe tekening
|
||||
start-open-file = Bestand openen…
|
||||
start-donate = Doneren
|
||||
start-send-feedback = Feedback verzenden
|
||||
start-sponsors = Sponsors
|
||||
start-tutorials = Zelfstudies
|
||||
start-loading-videos = Video's laden…
|
||||
start-videos-online = Video's worden via internet geladen.
|
||||
start-open-playlist = Afspeellijst openen op YouTube
|
||||
start-discussions = Discussies
|
||||
start-pinned = Vastgezet
|
||||
start-loading-discussions = Discussies laden…
|
||||
start-discussions-online = Discussies worden geladen vanaf GitHub.
|
||||
start-open-discussions = Discussies openen op GitHub
|
||||
start-supporters = Ondersteuners
|
||||
start-support-on-patreon = Ondersteunen op Patreon
|
||||
start-recent-files = Recente bestanden
|
||||
start-videos = Video's
|
||||
start-welcome = Welkom
|
||||
start-recent-documents = Recente documenten
|
||||
start-no-recent-files = Bestanden die u opent, verschijnen hier.
|
||||
start-browser-storage = Browseropslag
|
||||
start-keep-recent-files = Recente bestanden bewaren
|
||||
|
||||
modal-about = Info
|
||||
modal-keyboard-shortcuts = Sneltoetsen
|
||||
modal-command-aliases = Opdrachtaliassen
|
||||
modal-find-replace = Zoeken en vervangen
|
||||
modal-plugin-manager = Plug-inbeheer
|
||||
modal-update-available = Update beschikbaar
|
||||
modal-layer-manager = Lagenbeheer
|
||||
modal-layer-state-manager = Laagstatusbeheer
|
||||
modal-edit-layer-state = Laagstatus bewerken
|
||||
modal-plot = Afdrukken
|
||||
modal-layout-manager = Lay-outbeheer
|
||||
modal-scale-manager = Schaalbeheer
|
||||
modal-annotation-object-scale = Schaal van annotatieobject
|
||||
modal-plot-style-editor = Afdrukstijleditor
|
||||
modal-text-style-manager = Tekststijlbeheer
|
||||
modal-multiline-style-manager = Meervoudige-lijnstijlbeheer
|
||||
modal-table-style-manager = Tabelstijlbeheer
|
||||
modal-multileader-style-manager = Multileaderstijlbeheer
|
||||
modal-dimension-style-manager = Maatstijlbeheer
|
||||
modal-default-application = Standaardtoepassing
|
||||
modal-save-warning = Opslagwaarschuwing
|
||||
modal-unable-save = Tekening kan niet worden opgeslagen
|
||||
modal-drawing-changed = Tekening gewijzigd op schijf
|
||||
modal-delete-layer = Laag verwijderen
|
||||
modal-unsaved-changes = Niet-opgeslagen wijzigingen
|
||||
modal-point-style = Puntstijl
|
||||
modal-attribute-editor = Kenmerkeditor
|
||||
modal-save-drawing-as = Tekening opslaan als
|
||||
|
||||
command-move-base =
|
||||
MOVE Geef het basispunt op [{ $count ->
|
||||
[one] { $count } object
|
||||
*[other] { $count } objecten
|
||||
}]:
|
||||
command-move-target = MOVE Geef de bestemming op [basis { $x },{ $y }]:
|
||||
command-copy-array-count = COPY Voer het aantal items in de matrix in:
|
||||
command-copy-base =
|
||||
COPY Geef het basispunt op [{ $count ->
|
||||
[one] { $count } object
|
||||
*[other] { $count } objecten
|
||||
}]:
|
||||
command-copy-array-target = COPY Geef het tweede punt voor de matrix met { $count } items op [basis { $x },{ $y }]:
|
||||
command-copy-target =
|
||||
COPY Geef de bestemming op [{ $count ->
|
||||
[one] { $count } kopie tot nu toe
|
||||
*[other] { $count } kopieën tot nu toe
|
||||
} | Matrix | Enter=gereed | basis { $x },{ $y }]:
|
||||
116
locales/ru-RU/opencadstudio.ftl
Normal file
116
locales/ru-RU/opencadstudio.ftl
Normal file
|
|
@ -0,0 +1,116 @@
|
|||
language-system = Язык системы
|
||||
language-english = English
|
||||
language-turkish = Türkçe
|
||||
language-dutch = Nederlands
|
||||
language-french = Français
|
||||
language-german = Deutsch
|
||||
language-hindi = हिन्दी
|
||||
language-russian = Русский
|
||||
language-chinese-simplified = 简体中文
|
||||
|
||||
action-close = Закрыть
|
||||
action-options = Параметры
|
||||
action-plugins = Плагины
|
||||
|
||||
ribbon-tab-draw = Рисование
|
||||
ribbon-tab-annotate = Аннотации
|
||||
ribbon-tab-insert = Вставка
|
||||
ribbon-tab-model = Модель
|
||||
ribbon-tab-layout = Лист
|
||||
ribbon-tab-manage = Управление
|
||||
ribbon-tab-view = Вид
|
||||
|
||||
options-language-section = Язык
|
||||
options-language-label = Язык интерфейса:
|
||||
options-open-save-section = Открытие и сохранение
|
||||
options-default-save-format-label = Формат сохранения по умолчанию:
|
||||
options-default-save-format-help = Используется при первом сохранении нового чертежа. Существующие чертежи сохраняют тип и версию файла.
|
||||
options-theme-section = Тема
|
||||
options-theme-label = Тема приложения:
|
||||
options-theme-help = Изменение базового цвета включает пользовательскую тему. Все оттенки компонентов создаются из этих шести цветов.
|
||||
options-color-background = Фон
|
||||
options-color-text = Текст
|
||||
options-color-primary = Основной
|
||||
options-color-success = Успех
|
||||
options-color-warning = Предупреждение
|
||||
options-color-danger = Опасность
|
||||
|
||||
command-line-ready = Open CAD Studio готов.
|
||||
command-line-hint = Введите команду или используйте ленту. Откройте OBJ на вкладке «Вставка».
|
||||
command-line-label = Команда:
|
||||
command-line-literal-spaces = Буквальные пробелы: пробел остаётся в строке, а не запускает команду. Режим действует до отключения.
|
||||
|
||||
start-new-drawing = Новый чертёж
|
||||
start-open-file = Открыть файл…
|
||||
start-donate = Поддержать
|
||||
start-send-feedback = Отправить отзыв
|
||||
start-sponsors = Спонсоры
|
||||
start-tutorials = Учебные материалы
|
||||
start-loading-videos = Загрузка видео…
|
||||
start-videos-online = Видео загружаются из Интернета.
|
||||
start-open-playlist = Открыть плейлист на YouTube
|
||||
start-discussions = Обсуждения
|
||||
start-pinned = Закреплено
|
||||
start-loading-discussions = Загрузка обсуждений…
|
||||
start-discussions-online = Обсуждения загружаются с GitHub.
|
||||
start-open-discussions = Открыть обсуждения на GitHub
|
||||
start-supporters = Сторонники
|
||||
start-support-on-patreon = Поддержать на Patreon
|
||||
start-recent-files = Недавние файлы
|
||||
start-videos = Видео
|
||||
start-welcome = Добро пожаловать
|
||||
start-recent-documents = Недавние документы
|
||||
start-no-recent-files = Открытые вами файлы появятся здесь.
|
||||
start-browser-storage = Хранилище браузера
|
||||
start-keep-recent-files = Хранить недавние файлы
|
||||
|
||||
modal-about = О программе
|
||||
modal-keyboard-shortcuts = Сочетания клавиш
|
||||
modal-command-aliases = Псевдонимы команд
|
||||
modal-find-replace = Найти и заменить
|
||||
modal-plugin-manager = Диспетчер плагинов
|
||||
modal-update-available = Доступно обновление
|
||||
modal-layer-manager = Диспетчер слоёв
|
||||
modal-layer-state-manager = Диспетчер состояний слоёв
|
||||
modal-edit-layer-state = Изменить состояние слоя
|
||||
modal-plot = Печать
|
||||
modal-layout-manager = Диспетчер листов
|
||||
modal-scale-manager = Диспетчер масштабов
|
||||
modal-annotation-object-scale = Масштаб аннотативного объекта
|
||||
modal-plot-style-editor = Редактор стилей печати
|
||||
modal-text-style-manager = Диспетчер стилей текста
|
||||
modal-multiline-style-manager = Диспетчер стилей мультилиний
|
||||
modal-table-style-manager = Диспетчер стилей таблиц
|
||||
modal-multileader-style-manager = Диспетчер стилей мультивыносок
|
||||
modal-dimension-style-manager = Диспетчер стилей размеров
|
||||
modal-default-application = Приложение по умолчанию
|
||||
modal-save-warning = Предупреждение о сохранении
|
||||
modal-unable-save = Не удалось сохранить чертёж
|
||||
modal-drawing-changed = Чертёж изменён на диске
|
||||
modal-delete-layer = Удалить слой
|
||||
modal-unsaved-changes = Несохранённые изменения
|
||||
modal-point-style = Стиль точек
|
||||
modal-attribute-editor = Редактор атрибутов
|
||||
modal-save-drawing-as = Сохранить чертёж как
|
||||
|
||||
command-move-base =
|
||||
MOVE Укажите базовую точку [{ $count ->
|
||||
[one] { $count } объект
|
||||
[few] { $count } объекта
|
||||
*[many] { $count } объектов
|
||||
}]:
|
||||
command-move-target = MOVE Укажите точку назначения [база { $x },{ $y }]:
|
||||
command-copy-array-count = COPY Введите число элементов массива:
|
||||
command-copy-base =
|
||||
COPY Укажите базовую точку [{ $count ->
|
||||
[one] { $count } объект
|
||||
[few] { $count } объекта
|
||||
*[many] { $count } объектов
|
||||
}]:
|
||||
command-copy-array-target = COPY Укажите вторую точку массива из { $count } элементов [база { $x },{ $y }]:
|
||||
command-copy-target =
|
||||
COPY Укажите точку назначения [{ $count ->
|
||||
[one] создана { $count } копия
|
||||
[few] создано { $count } копии
|
||||
*[many] создано { $count } копий
|
||||
} | Массив | Enter=готово | база { $x },{ $y }]:
|
||||
101
locales/tr-TR/opencadstudio.ftl
Normal file
101
locales/tr-TR/opencadstudio.ftl
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
language-system = Sistem dili
|
||||
language-english = English
|
||||
language-turkish = Türkçe
|
||||
language-dutch = Nederlands
|
||||
language-french = Français
|
||||
language-german = Deutsch
|
||||
language-hindi = हिन्दी
|
||||
language-russian = Русский
|
||||
language-chinese-simplified = 简体中文
|
||||
|
||||
action-close = Kapat
|
||||
action-options = Seçenekler
|
||||
action-plugins = Eklentiler
|
||||
|
||||
ribbon-tab-draw = Çizim
|
||||
ribbon-tab-annotate = Açıklama
|
||||
ribbon-tab-insert = Ekle
|
||||
ribbon-tab-model = Model
|
||||
ribbon-tab-layout = Yerleşim
|
||||
ribbon-tab-manage = Yönet
|
||||
ribbon-tab-view = Görünüm
|
||||
|
||||
options-language-section = Dil
|
||||
options-language-label = Arayüz dili:
|
||||
options-open-save-section = Açma ve Kaydetme
|
||||
options-default-save-format-label = Varsayılan kayıt biçimi:
|
||||
options-default-save-format-help = Yeni bir çizimin ilk kaydında kullanılır. Mevcut çizimler dosya türünü ve sürümünü korur.
|
||||
options-theme-section = Tema
|
||||
options-theme-label = Uygulama teması:
|
||||
options-theme-help = Temel renklerden birini değiştirmek Özel temaya geçer. Tema, tüm bileşen tonlarını bu altı renkten üretir.
|
||||
options-color-background = Arka plan
|
||||
options-color-text = Metin
|
||||
options-color-primary = Ana renk
|
||||
options-color-success = Başarı
|
||||
options-color-warning = Uyarı
|
||||
options-color-danger = Tehlike
|
||||
|
||||
command-line-ready = Open CAD Studio hazır.
|
||||
command-line-hint = Bir komut yazın veya şeridi kullanın. OBJ dosyasını Ekle sekmesinden açın.
|
||||
command-line-label = Komut:
|
||||
command-line-literal-spaces = Değişmez boşluklar: Boşluk, komutu çalıştırmak yerine satırda kalır. Yeniden kapatılana kadar etkin kalır.
|
||||
|
||||
start-new-drawing = Yeni Çizim
|
||||
start-open-file = Dosya Aç…
|
||||
start-donate = Bağış Yap
|
||||
start-send-feedback = Geri Bildirim Gönder
|
||||
start-sponsors = Sponsorlar
|
||||
start-tutorials = Eğitimler
|
||||
start-loading-videos = Videolar yükleniyor…
|
||||
start-videos-online = Videolar internetten yüklenir.
|
||||
start-open-playlist = Oynatma listesini YouTube'da aç
|
||||
start-discussions = Tartışmalar
|
||||
start-pinned = Sabitlenmiş
|
||||
start-loading-discussions = Tartışmalar yükleniyor…
|
||||
start-discussions-online = Tartışmalar GitHub'dan yüklenir.
|
||||
start-open-discussions = Tartışmaları GitHub'da Aç
|
||||
start-supporters = Destekçiler
|
||||
start-support-on-patreon = Patreon'da Destekle
|
||||
start-recent-files = Son Dosyalar
|
||||
start-videos = Videolar
|
||||
start-welcome = Hoş Geldiniz
|
||||
start-recent-documents = Son Belgeler
|
||||
start-no-recent-files = Açtığınız dosyalar burada görünür.
|
||||
start-browser-storage = Tarayıcı depolama alanı
|
||||
start-keep-recent-files = Son dosyaları sakla
|
||||
|
||||
modal-about = Hakkında
|
||||
modal-keyboard-shortcuts = Klavye Kısayolları
|
||||
modal-command-aliases = Komut Kısaltmaları
|
||||
modal-find-replace = Bul ve Değiştir
|
||||
modal-plugin-manager = Eklenti Yöneticisi
|
||||
modal-update-available = Güncelleme Var
|
||||
modal-layer-manager = Katman Yöneticisi
|
||||
modal-layer-state-manager = Katman Durumu Yöneticisi
|
||||
modal-edit-layer-state = Katman Durumunu Düzenle
|
||||
modal-plot = Yazdır
|
||||
modal-layout-manager = Yerleşim Yöneticisi
|
||||
modal-scale-manager = Ölçek Yöneticisi
|
||||
modal-annotation-object-scale = Açıklama Nesnesi Ölçeği
|
||||
modal-plot-style-editor = Yazdırma Stili Düzenleyicisi
|
||||
modal-text-style-manager = Metin Stili Yöneticisi
|
||||
modal-multiline-style-manager = Çoklu Çizgi Stili Yöneticisi
|
||||
modal-table-style-manager = Tablo Stili Yöneticisi
|
||||
modal-multileader-style-manager = Çoklu Kılavuz Stili Yöneticisi
|
||||
modal-dimension-style-manager = Ölçülendirme Stili Yöneticisi
|
||||
modal-default-application = Varsayılan Uygulama
|
||||
modal-save-warning = Kayıt Uyarısı
|
||||
modal-unable-save = Çizim Kaydedilemiyor
|
||||
modal-drawing-changed = Çizim Diskte Değişti
|
||||
modal-delete-layer = Katmanı Sil
|
||||
modal-unsaved-changes = Kaydedilmemiş Değişiklikler
|
||||
modal-point-style = Nokta Stili
|
||||
modal-attribute-editor = Öznitelik Düzenleyicisi
|
||||
modal-save-drawing-as = Çizimi Farklı Kaydet
|
||||
|
||||
command-move-base = MOVE Temel noktayı belirtin [{ $count } nesne]:
|
||||
command-move-target = MOVE Hedef noktayı belirtin [temel { $x },{ $y }]:
|
||||
command-copy-array-count = COPY Dizideki öğe sayısını girin:
|
||||
command-copy-base = COPY Temel noktayı belirtin [{ $count } nesne]:
|
||||
command-copy-array-target = COPY { $count } öğeli dizi için ikinci noktayı belirtin [temel { $x },{ $y }]:
|
||||
command-copy-target = COPY Hedef noktayı belirtin [şimdiye kadar { $count } kopya | Dizi | Enter=tamam | temel { $x },{ $y }]:
|
||||
101
locales/zh-CN/opencadstudio.ftl
Normal file
101
locales/zh-CN/opencadstudio.ftl
Normal file
|
|
@ -0,0 +1,101 @@
|
|||
language-system = 跟随系统
|
||||
language-english = English
|
||||
language-turkish = Türkçe
|
||||
language-dutch = Nederlands
|
||||
language-french = Français
|
||||
language-german = Deutsch
|
||||
language-hindi = हिन्दी
|
||||
language-russian = Русский
|
||||
language-chinese-simplified = 简体中文
|
||||
|
||||
action-close = 关闭
|
||||
action-options = 选项
|
||||
action-plugins = 插件
|
||||
|
||||
ribbon-tab-draw = 绘图
|
||||
ribbon-tab-annotate = 注释
|
||||
ribbon-tab-insert = 插入
|
||||
ribbon-tab-model = 模型
|
||||
ribbon-tab-layout = 布局
|
||||
ribbon-tab-manage = 管理
|
||||
ribbon-tab-view = 视图
|
||||
|
||||
options-language-section = 语言
|
||||
options-language-label = 界面语言:
|
||||
options-open-save-section = 打开和保存
|
||||
options-default-save-format-label = 默认保存格式:
|
||||
options-default-save-format-help = 用于新图形的首次保存。现有图形保留其文件类型和版本。
|
||||
options-theme-section = 主题
|
||||
options-theme-label = 应用程序主题:
|
||||
options-theme-help = 更改基础颜色会切换到自定义主题。主题将从这六种颜色生成所有组件色调。
|
||||
options-color-background = 背景
|
||||
options-color-text = 文字
|
||||
options-color-primary = 主要
|
||||
options-color-success = 成功
|
||||
options-color-warning = 警告
|
||||
options-color-danger = 危险
|
||||
|
||||
command-line-ready = Open CAD Studio 已就绪。
|
||||
command-line-hint = 输入命令或使用功能区。可从“插入”选项卡打开 OBJ。
|
||||
command-line-label = 命令:
|
||||
command-line-literal-spaces = 保留空格:空格会留在输入行中而不执行命令,直到再次切换此模式。
|
||||
|
||||
start-new-drawing = 新建图形
|
||||
start-open-file = 打开文件…
|
||||
start-donate = 捐赠
|
||||
start-send-feedback = 发送反馈
|
||||
start-sponsors = 赞助商
|
||||
start-tutorials = 教程
|
||||
start-loading-videos = 正在加载视频…
|
||||
start-videos-online = 视频通过互联网加载。
|
||||
start-open-playlist = 在 YouTube 上打开播放列表
|
||||
start-discussions = 讨论
|
||||
start-pinned = 已置顶
|
||||
start-loading-discussions = 正在加载讨论…
|
||||
start-discussions-online = 讨论从 GitHub 加载。
|
||||
start-open-discussions = 在 GitHub 上打开讨论
|
||||
start-supporters = 支持者
|
||||
start-support-on-patreon = 在 Patreon 上支持
|
||||
start-recent-files = 最近文件
|
||||
start-videos = 视频
|
||||
start-welcome = 欢迎
|
||||
start-recent-documents = 最近使用的文档
|
||||
start-no-recent-files = 您打开的文件将显示在此处。
|
||||
start-browser-storage = 浏览器存储
|
||||
start-keep-recent-files = 保留最近文件
|
||||
|
||||
modal-about = 关于
|
||||
modal-keyboard-shortcuts = 键盘快捷键
|
||||
modal-command-aliases = 命令别名
|
||||
modal-find-replace = 查找和替换
|
||||
modal-plugin-manager = 插件管理器
|
||||
modal-update-available = 有可用更新
|
||||
modal-layer-manager = 图层管理器
|
||||
modal-layer-state-manager = 图层状态管理器
|
||||
modal-edit-layer-state = 编辑图层状态
|
||||
modal-plot = 打印
|
||||
modal-layout-manager = 布局管理器
|
||||
modal-scale-manager = 比例管理器
|
||||
modal-annotation-object-scale = 注释对象比例
|
||||
modal-plot-style-editor = 打印样式编辑器
|
||||
modal-text-style-manager = 文字样式管理器
|
||||
modal-multiline-style-manager = 多线样式管理器
|
||||
modal-table-style-manager = 表格样式管理器
|
||||
modal-multileader-style-manager = 多重引线样式管理器
|
||||
modal-dimension-style-manager = 标注样式管理器
|
||||
modal-default-application = 默认应用程序
|
||||
modal-save-warning = 保存警告
|
||||
modal-unable-save = 无法保存图形
|
||||
modal-drawing-changed = 磁盘上的图形已更改
|
||||
modal-delete-layer = 删除图层
|
||||
modal-unsaved-changes = 未保存的更改
|
||||
modal-point-style = 点样式
|
||||
modal-attribute-editor = 属性编辑器
|
||||
modal-save-drawing-as = 图形另存为
|
||||
|
||||
command-move-base = MOVE 指定基点 [{ $count } 个对象]:
|
||||
command-move-target = MOVE 指定目标点 [基点 { $x },{ $y }]:
|
||||
command-copy-array-count = COPY 输入阵列项目数:
|
||||
command-copy-base = COPY 指定基点 [{ $count } 个对象]:
|
||||
command-copy-array-target = COPY 为 { $count } 项阵列指定第二点 [基点 { $x },{ $y }]:
|
||||
command-copy-target = COPY 指定目标点 [已复制 { $count } 个 | 阵列 | 回车=完成 | 基点 { $x },{ $y }]:
|
||||
|
|
@ -855,6 +855,8 @@ pub(super) struct OpenCADStudio {
|
|||
save_dialog_for_unsaved: bool,
|
||||
/// User preference for the first save of a new/unsaved drawing.
|
||||
default_save_format: String,
|
||||
/// Persisted interface language selection.
|
||||
language: crate::i18n::Language,
|
||||
|
||||
// ── DimStyle Dialog ───────────────────────────────────────────────────
|
||||
/// Name of the style currently shown in the dialog.
|
||||
|
|
@ -1602,6 +1604,8 @@ pub enum Message {
|
|||
OptionsThemeChanged(String),
|
||||
/// Edit one of Custom theme's six base colours as #RRGGBB.
|
||||
OptionsThemeColorChanged(usize, String),
|
||||
/// Switch the interface language and redraw localized views.
|
||||
LanguageChanged(crate::i18n::Language),
|
||||
ClearScene,
|
||||
SetWireframe(bool),
|
||||
/// Set the active tab's render mode (one of acadrust's seven visual
|
||||
|
|
@ -2648,6 +2652,10 @@ impl OpenCADStudio {
|
|||
}
|
||||
|
||||
fn new() -> Self {
|
||||
let config = config::AppConfig::load();
|
||||
if let Err(error) = crate::i18n::set_language(config.settings.language) {
|
||||
eprintln!("Unable to apply saved UI language: {error}");
|
||||
}
|
||||
// Boot with only the Welcome/Start tab. The user creates drawings
|
||||
// explicitly (File → New); we never auto-spawn Drawing1.
|
||||
let start_tab = DocumentTab::new_start();
|
||||
|
|
@ -2827,6 +2835,7 @@ impl OpenCADStudio {
|
|||
save_dialog_filename: "drawing.dwg".to_string(),
|
||||
save_dialog_for_unsaved: false,
|
||||
default_save_format: crate::io::DEFAULT_SAVE_FORMAT.to_string(),
|
||||
language: crate::i18n::Language::default(),
|
||||
// Plot style
|
||||
active_plot_style: crate::io::plot_style::PlotStyleTable::load_named(
|
||||
crate::io::plot_style::DEFAULT_PLOT_STYLE,
|
||||
|
|
@ -2997,7 +3006,7 @@ impl OpenCADStudio {
|
|||
// so preferences, recents, status-bar layout, ribbon density and print
|
||||
// options survive across sessions (issue #68). `last_saved_config` is
|
||||
// seeded below so the first change — not the boot — triggers a write.
|
||||
app.apply_config(config::AppConfig::load());
|
||||
app.apply_config(config);
|
||||
// Load command aliases from ocad.pgp (writes the shipped default file
|
||||
// on first launch). The hide-set keeps aliases out of autocomplete while
|
||||
// their target command still shows.
|
||||
|
|
|
|||
|
|
@ -151,6 +151,9 @@ pub struct UserSettings {
|
|||
/// (#188).
|
||||
pub bg_color: Option<[u8; 3]>,
|
||||
pub paper_bg_color: Option<[u8; 3]>,
|
||||
/// Interface language preference. `System` negotiates against the
|
||||
/// platform locale on every launch.
|
||||
pub language: crate::i18n::Language,
|
||||
}
|
||||
|
||||
impl Default for UserSettings {
|
||||
|
|
@ -177,6 +180,7 @@ impl Default for UserSettings {
|
|||
pick_drag_rect: false,
|
||||
bg_color: None,
|
||||
paper_bg_color: None,
|
||||
language: crate::i18n::Language::default(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -288,6 +288,7 @@ impl OpenCADStudio {
|
|||
pick_drag_rect: self.pick_drag_rect,
|
||||
bg_color: self.default_bg_color.map(f4_to_u3),
|
||||
paper_bg_color: self.default_paper_bg_color.map(f4_to_u3),
|
||||
language: self.language,
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -317,6 +318,9 @@ impl OpenCADStudio {
|
|||
self.pick_drag_rect = s.pick_drag_rect;
|
||||
self.default_bg_color = s.bg_color.map(u3_to_f4);
|
||||
self.default_paper_bg_color = s.paper_bg_color.map(u3_to_f4);
|
||||
if crate::i18n::set_language(s.language).is_ok() {
|
||||
self.language = s.language;
|
||||
}
|
||||
// Push the restored background onto every drawing tab that exists now
|
||||
// (the start tab and any initial drawing). Tabs created later pick it
|
||||
// up via `apply_bg_default` at their construction site.
|
||||
|
|
|
|||
|
|
@ -4323,6 +4323,22 @@ impl OpenCADStudio {
|
|||
Task::none()
|
||||
}
|
||||
|
||||
Message::LanguageChanged(language) => {
|
||||
if self.language == language {
|
||||
return Task::none();
|
||||
}
|
||||
match crate::i18n::set_language(language) {
|
||||
Ok(()) => {
|
||||
self.language = language;
|
||||
self.persist_settings_if_changed();
|
||||
}
|
||||
Err(error) => self
|
||||
.command_line
|
||||
.push_error(&format!("Unable to change UI language: {error}")),
|
||||
}
|
||||
Task::none()
|
||||
}
|
||||
|
||||
Message::AboutOpen => {
|
||||
self.active_modal = Some(super::ModalKind::About);
|
||||
Task::none()
|
||||
|
|
|
|||
|
|
@ -2318,7 +2318,7 @@ fn start_page_content<'a>(
|
|||
let headline = text("Open CAD Studio").size(40).style(start_primary_style);
|
||||
|
||||
// Plain outlined button (Open / New / Help / Contribute).
|
||||
let outline_btn = |label: &'static str, msg: Message| {
|
||||
let outline_btn = |label: String, msg: Message| {
|
||||
button(text(label).size(14))
|
||||
.on_press(msg)
|
||||
.padding([10, 22])
|
||||
|
|
@ -2346,7 +2346,7 @@ fn start_page_content<'a>(
|
|||
button(
|
||||
row![
|
||||
crate::ui::icons::themed_danger_text(crate::ui::icons::HEART, 14.0),
|
||||
text("Donate").size(14),
|
||||
text(crate::tr!("start-donate")).size(14),
|
||||
]
|
||||
.spacing(5)
|
||||
.align_y(iced::Center),
|
||||
|
|
@ -2360,8 +2360,8 @@ fn start_page_content<'a>(
|
|||
};
|
||||
|
||||
let primary_row = WrapFlow::new(vec![
|
||||
outline_btn("New Drawing", Message::TabNew).into(),
|
||||
outline_btn("Open File…", Message::OpenFile).into(),
|
||||
outline_btn(crate::tr!("start-new-drawing"), Message::TabNew).into(),
|
||||
outline_btn(crate::tr!("start-open-file"), Message::OpenFile).into(),
|
||||
donate_btn.into(),
|
||||
])
|
||||
.spacing_x(12.0)
|
||||
|
|
@ -2371,16 +2371,16 @@ fn start_page_content<'a>(
|
|||
#[cfg_attr(target_arch = "wasm32", allow(unused_mut))]
|
||||
let mut secondary_items: Vec<Element<'a, Message>> = vec![
|
||||
outline_btn(
|
||||
"Send Feedback",
|
||||
crate::tr!("start-send-feedback"),
|
||||
Message::RibbonToolClick {
|
||||
tool_id: "REPORT".to_string(),
|
||||
event: crate::modules::ModuleEvent::Command("REPORT".to_string()),
|
||||
},
|
||||
)
|
||||
.into(),
|
||||
outline_btn("Options", Message::OptionsOpen).into(),
|
||||
outline_btn(crate::tr!("action-options"), Message::OptionsOpen).into(),
|
||||
];
|
||||
secondary_items.push(outline_btn("Plugins", Message::PluginManagerOpen).into());
|
||||
secondary_items.push(outline_btn(crate::tr!("action-plugins"), Message::PluginManagerOpen).into());
|
||||
// The web build is already in the browser, so only the desktop offers a
|
||||
// link to the web version.
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
|
|
@ -2403,7 +2403,7 @@ fn start_page_content<'a>(
|
|||
.report_natural_width(action_width_out.clone());
|
||||
|
||||
let sponsors = column![
|
||||
text("Sponsors").size(15),
|
||||
text(crate::tr!("start-sponsors")).size(15),
|
||||
mouse_area(
|
||||
container(
|
||||
iced::widget::svg(iced::widget::svg::Handle::from_memory(include_bytes!(
|
||||
|
|
@ -2505,7 +2505,7 @@ fn start_page_content<'a>(
|
|||
// whole thumbnail remains visible when that width changes.
|
||||
let thumb_h =
|
||||
(panel_w - VIDEO_PANEL_PADDING * 2.0 - VIDEO_SCROLL_GUTTER) * 9.0 / 16.0;
|
||||
let mut list = column![text("Tutorials").size(15)]
|
||||
let mut list = column![text(crate::tr!("start-tutorials")).size(15)]
|
||||
.spacing(10)
|
||||
.width(Fill)
|
||||
// Keep the scrollbar off the thumbnails.
|
||||
|
|
@ -2545,14 +2545,14 @@ fn start_page_content<'a>(
|
|||
}
|
||||
if videos.is_empty() {
|
||||
let note = if videos_loading {
|
||||
"Loading videos…"
|
||||
crate::tr!("start-loading-videos")
|
||||
} else {
|
||||
"Videos load from the internet."
|
||||
crate::tr!("start-videos-online")
|
||||
};
|
||||
list = list.push(text(note).size(12).style(start_muted_style));
|
||||
}
|
||||
let playlist_btn = mouse_area(
|
||||
container(text("Open playlist on YouTube").size(12))
|
||||
container(text(crate::tr!("start-open-playlist")).size(12))
|
||||
.padding([6, 10])
|
||||
.width(Fill)
|
||||
.center_x(Fill)
|
||||
|
|
@ -2605,7 +2605,7 @@ fn start_page_content<'a>(
|
|||
// web builds read the CI-generated snapshot. Both sources mark pinned
|
||||
// discussions and sort them before the rest of the list.
|
||||
let discussions_panel: Element<'a, Message> = {
|
||||
let mut list = column![text("Discussions").size(15)]
|
||||
let mut list = column![text(crate::tr!("start-discussions")).size(15)]
|
||||
.spacing(8)
|
||||
.width(Fill);
|
||||
for discussion in discussions {
|
||||
|
|
@ -2618,7 +2618,7 @@ fn start_page_content<'a>(
|
|||
.align_y(iced::Center);
|
||||
if discussion.pinned {
|
||||
meta = meta.push(
|
||||
text("Pinned")
|
||||
text(crate::tr!("start-pinned"))
|
||||
.size(10)
|
||||
.style(start_primary_style),
|
||||
);
|
||||
|
|
@ -2661,14 +2661,14 @@ fn start_page_content<'a>(
|
|||
}
|
||||
if discussions.is_empty() {
|
||||
let note = if discussions_loading {
|
||||
"Loading discussions…"
|
||||
crate::tr!("start-loading-discussions")
|
||||
} else {
|
||||
"Discussions load from GitHub."
|
||||
crate::tr!("start-discussions-online")
|
||||
};
|
||||
list = list.push(text(note).size(12).style(start_muted_style));
|
||||
}
|
||||
let open_btn = mouse_area(
|
||||
container(text("Open Discussions on GitHub").size(12))
|
||||
container(text(crate::tr!("start-open-discussions")).size(12))
|
||||
.padding([6, 10])
|
||||
.width(Fill)
|
||||
.center_x(Fill)
|
||||
|
|
@ -2725,7 +2725,7 @@ fn start_page_content<'a>(
|
|||
// shows, so the rail always invites support.
|
||||
let supporters: Element<'a, Message> = {
|
||||
let mut list = column![
|
||||
text("Supporters").size(15),
|
||||
text(crate::tr!("start-supporters")).size(15),
|
||||
Space::new().height(iced::Length::Fixed(12.0)),
|
||||
]
|
||||
.spacing(6)
|
||||
|
|
@ -2746,7 +2746,7 @@ fn start_page_content<'a>(
|
|||
container(
|
||||
iced::widget::row![
|
||||
crate::ui::icons::themed_danger_text(crate::ui::icons::HEART, 13.0),
|
||||
text("Support on Patreon").size(12),
|
||||
text(crate::tr!("start-support-on-patreon")).size(12),
|
||||
]
|
||||
.spacing(6)
|
||||
.align_y(iced::Center),
|
||||
|
|
@ -2831,7 +2831,7 @@ fn start_page_content<'a>(
|
|||
.height(Fill)
|
||||
.into(),
|
||||
StartLayout::Compact => {
|
||||
let tab_btn = |label: &'static str, section: super::StartSection| {
|
||||
let tab_btn = |label: String, section: super::StartSection| {
|
||||
let is_active = active == section;
|
||||
button(text(label).size(14))
|
||||
.on_press(Message::StartSectionSelect(section))
|
||||
|
|
@ -2864,11 +2864,11 @@ fn start_page_content<'a>(
|
|||
})
|
||||
};
|
||||
let tab_bar = Row::with_children(vec![
|
||||
tab_btn("Recent Files", super::StartSection::Recent).into(),
|
||||
tab_btn("Videos", super::StartSection::Videos).into(),
|
||||
tab_btn("Welcome", super::StartSection::Welcome).into(),
|
||||
tab_btn("Discussions", super::StartSection::Discussions).into(),
|
||||
tab_btn("Supporters", super::StartSection::Supporters).into(),
|
||||
tab_btn(crate::tr!("start-recent-files"), super::StartSection::Recent).into(),
|
||||
tab_btn(crate::tr!("start-videos"), super::StartSection::Videos).into(),
|
||||
tab_btn(crate::tr!("start-welcome"), super::StartSection::Welcome).into(),
|
||||
tab_btn(crate::tr!("start-discussions"), super::StartSection::Discussions).into(),
|
||||
tab_btn(crate::tr!("start-supporters"), super::StartSection::Supporters).into(),
|
||||
])
|
||||
.spacing(6.0)
|
||||
.align_y(iced::Center)
|
||||
|
|
@ -2944,11 +2944,11 @@ pub(super) fn recent_files_panel<'a>(
|
|||
) -> Element<'a, Message> {
|
||||
// Title mirrors the Supporters rail: size 15 in the bright text colour,
|
||||
// followed by a 12px gap before the content.
|
||||
let title = text("Recent Documents").size(15);
|
||||
let title = text(crate::tr!("start-recent-documents")).size(15);
|
||||
|
||||
let body: Element<'a, Message> = if recents.is_empty() {
|
||||
container(
|
||||
text("Files you open will show up here.")
|
||||
text(crate::tr!("start-no-recent-files"))
|
||||
.size(12)
|
||||
.style(start_muted_style)
|
||||
)
|
||||
|
|
@ -2976,7 +2976,7 @@ pub(super) fn recent_files_panel<'a>(
|
|||
// directory line.
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let dir = if dir.is_empty() {
|
||||
"Browser storage".to_string()
|
||||
crate::tr!("start-browser-storage")
|
||||
} else {
|
||||
dir
|
||||
};
|
||||
|
|
@ -3087,7 +3087,7 @@ pub(super) fn recent_files_panel<'a>(
|
|||
.padding([2, 6])
|
||||
.width(iced::Length::Fixed(46.0));
|
||||
let limit_row = row![
|
||||
text("Keep recent files").size(11).style(start_muted_style).width(Fill),
|
||||
text(crate::tr!("start-keep-recent-files")).size(11).style(start_muted_style).width(Fill),
|
||||
button(crate::ui::icons::themed(crate::ui::icons::MINUS, 11.0))
|
||||
.on_press(Message::SetRecentLimit(shown.saturating_sub(STEP)))
|
||||
.padding([3, 6])
|
||||
|
|
|
|||
|
|
@ -5,41 +5,41 @@ use iced::{Background, Element, Fill, Fit, Theme};
|
|||
impl OpenCADStudio {
|
||||
/// Title shown in the active modal's title bar. Keep in sync with the
|
||||
/// [`Self::modal_content`] dispatch.
|
||||
pub(super) fn modal_title(&self) -> &'static str {
|
||||
pub(super) fn modal_title(&self) -> String {
|
||||
use super::super::ModalKind as K;
|
||||
match self.active_modal {
|
||||
Some(K::About) => "About",
|
||||
Some(K::Shortcuts) => "Keyboard Shortcuts",
|
||||
Some(K::Aliases) => "Command Aliases",
|
||||
Some(K::Options) => "Options",
|
||||
Some(K::FindReplace) => "Find and Replace",
|
||||
Some(K::PluginManager) => "Plugin Manager",
|
||||
Some(K::UpdateNotice) => "Update Available",
|
||||
Some(K::Layers) => "Layer Manager",
|
||||
Some(K::LayerStateManager) => "Layer State Manager",
|
||||
Some(K::LayerStateEditor) => "Edit Layer State",
|
||||
Some(K::Plot) => "Plot",
|
||||
Some(K::LayoutManager) => "Layout Manager",
|
||||
Some(K::ScaleManager) => "Scale Manager",
|
||||
Some(K::AnnoObjectScale) => "Annotation Object Scale",
|
||||
Some(K::Plotstyle) => "Plot Style Editor",
|
||||
Some(K::TextStyle) => "Text Style Manager",
|
||||
Some(K::MlStyle) => "Multiline Style Manager",
|
||||
Some(K::TableStyle) => "Table Style Manager",
|
||||
Some(K::MLeaderStyle) => "Multileader Style Manager",
|
||||
Some(K::DimStyle) => "Dimension Style Manager",
|
||||
Some(K::AssocPrompt) => "Default Application",
|
||||
Some(K::AecDropWarning) => "Save Warning",
|
||||
Some(K::About) => crate::tr!("modal-about"),
|
||||
Some(K::Shortcuts) => crate::tr!("modal-keyboard-shortcuts"),
|
||||
Some(K::Aliases) => crate::tr!("modal-command-aliases"),
|
||||
Some(K::Options) => crate::tr!("action-options"),
|
||||
Some(K::FindReplace) => crate::tr!("modal-find-replace"),
|
||||
Some(K::PluginManager) => crate::tr!("modal-plugin-manager"),
|
||||
Some(K::UpdateNotice) => crate::tr!("modal-update-available"),
|
||||
Some(K::Layers) => crate::tr!("modal-layer-manager"),
|
||||
Some(K::LayerStateManager) => crate::tr!("modal-layer-state-manager"),
|
||||
Some(K::LayerStateEditor) => crate::tr!("modal-edit-layer-state"),
|
||||
Some(K::Plot) => crate::tr!("modal-plot"),
|
||||
Some(K::LayoutManager) => crate::tr!("modal-layout-manager"),
|
||||
Some(K::ScaleManager) => crate::tr!("modal-scale-manager"),
|
||||
Some(K::AnnoObjectScale) => crate::tr!("modal-annotation-object-scale"),
|
||||
Some(K::Plotstyle) => crate::tr!("modal-plot-style-editor"),
|
||||
Some(K::TextStyle) => crate::tr!("modal-text-style-manager"),
|
||||
Some(K::MlStyle) => crate::tr!("modal-multiline-style-manager"),
|
||||
Some(K::TableStyle) => crate::tr!("modal-table-style-manager"),
|
||||
Some(K::MLeaderStyle) => crate::tr!("modal-multileader-style-manager"),
|
||||
Some(K::DimStyle) => crate::tr!("modal-dimension-style-manager"),
|
||||
Some(K::AssocPrompt) => crate::tr!("modal-default-application"),
|
||||
Some(K::AecDropWarning) => crate::tr!("modal-save-warning"),
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Some(K::FileInUse) => "Unable to Save Drawing",
|
||||
Some(K::FileInUse) => crate::tr!("modal-unable-save"),
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
Some(K::ExternalChange) => "Drawing Changed on Disk",
|
||||
Some(K::LayerDeleteWarning) => "Delete Layer",
|
||||
Some(K::Unsaved) => "Unsaved Changes",
|
||||
Some(K::PointStyle) => "Point Style",
|
||||
Some(K::AttributeEditor) => "Attribute Editor",
|
||||
Some(K::SaveDialog) => "Save Drawing As",
|
||||
None => "",
|
||||
Some(K::ExternalChange) => crate::tr!("modal-drawing-changed"),
|
||||
Some(K::LayerDeleteWarning) => crate::tr!("modal-delete-layer"),
|
||||
Some(K::Unsaved) => crate::tr!("modal-unsaved-changes"),
|
||||
Some(K::PointStyle) => crate::tr!("modal-point-style"),
|
||||
Some(K::AttributeEditor) => crate::tr!("modal-attribute-editor"),
|
||||
Some(K::SaveDialog) => crate::tr!("modal-save-drawing-as"),
|
||||
None => String::new(),
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -90,6 +90,7 @@ impl OpenCADStudio {
|
|||
&self.default_save_format,
|
||||
&self.ui_theme,
|
||||
&self.theme_color_inputs,
|
||||
self.language,
|
||||
flow,
|
||||
)
|
||||
},
|
||||
|
|
|
|||
153
src/i18n.rs
Normal file
153
src/i18n.rs
Normal file
|
|
@ -0,0 +1,153 @@
|
|||
//! Application language selection and embedded Fluent resources.
|
||||
|
||||
use i18n_embed::fluent::{fluent_language_loader, FluentLanguageLoader};
|
||||
use i18n_embed::LanguageLoader;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
use i18n_embed::DesktopLanguageRequester;
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
use i18n_embed::WebLanguageRequester;
|
||||
use rust_embed::RustEmbed;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::sync::OnceLock;
|
||||
|
||||
#[derive(RustEmbed)]
|
||||
#[folder = "locales/"]
|
||||
struct Localizations;
|
||||
|
||||
/// User-selectable UI language. `System` keeps following the platform's
|
||||
/// preferred locale while explicit choices remain stable across restarts.
|
||||
#[derive(Clone, Copy, Debug, Default, Eq, PartialEq, Serialize, Deserialize)]
|
||||
pub enum Language {
|
||||
#[default]
|
||||
#[serde(rename = "system")]
|
||||
System,
|
||||
#[serde(rename = "en-US")]
|
||||
EnUs,
|
||||
#[serde(rename = "tr-TR")]
|
||||
TrTr,
|
||||
#[serde(rename = "nl-NL")]
|
||||
NlNl,
|
||||
#[serde(rename = "fr-FR")]
|
||||
FrFr,
|
||||
#[serde(rename = "de-DE")]
|
||||
DeDe,
|
||||
#[serde(rename = "hi-IN")]
|
||||
HiIn,
|
||||
#[serde(rename = "ru-RU")]
|
||||
RuRu,
|
||||
#[serde(rename = "zh-CN")]
|
||||
ZhCn,
|
||||
}
|
||||
|
||||
impl Language {
|
||||
pub const ALL: [Language; 9] = [
|
||||
Language::System,
|
||||
Language::EnUs,
|
||||
Language::TrTr,
|
||||
Language::NlNl,
|
||||
Language::FrFr,
|
||||
Language::DeDe,
|
||||
Language::HiIn,
|
||||
Language::RuRu,
|
||||
Language::ZhCn,
|
||||
];
|
||||
|
||||
fn requested(self) -> Vec<i18n_embed::unic_langid::LanguageIdentifier> {
|
||||
match self {
|
||||
Language::System => system_languages(),
|
||||
Language::EnUs => vec!["en-US".parse().expect("valid locale")],
|
||||
Language::TrTr => vec!["tr-TR".parse().expect("valid locale")],
|
||||
Language::NlNl => vec!["nl-NL".parse().expect("valid locale")],
|
||||
Language::FrFr => vec!["fr-FR".parse().expect("valid locale")],
|
||||
Language::DeDe => vec!["de-DE".parse().expect("valid locale")],
|
||||
Language::HiIn => vec!["hi-IN".parse().expect("valid locale")],
|
||||
Language::RuRu => vec!["ru-RU".parse().expect("valid locale")],
|
||||
Language::ZhCn => vec!["zh-CN".parse().expect("valid locale")],
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl std::fmt::Display for Language {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let label = match self {
|
||||
Language::System => crate::tr!("language-system"),
|
||||
Language::EnUs => crate::tr!("language-english"),
|
||||
Language::TrTr => crate::tr!("language-turkish"),
|
||||
Language::NlNl => crate::tr!("language-dutch"),
|
||||
Language::FrFr => crate::tr!("language-french"),
|
||||
Language::DeDe => crate::tr!("language-german"),
|
||||
Language::HiIn => crate::tr!("language-hindi"),
|
||||
Language::RuRu => crate::tr!("language-russian"),
|
||||
Language::ZhCn => crate::tr!("language-chinese-simplified"),
|
||||
};
|
||||
f.write_str(&label)
|
||||
}
|
||||
}
|
||||
|
||||
fn system_languages() -> Vec<i18n_embed::unic_langid::LanguageIdentifier> {
|
||||
#[cfg(target_arch = "wasm32")]
|
||||
let requested = WebLanguageRequester::requested_languages();
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
let requested = DesktopLanguageRequester::requested_languages();
|
||||
requested
|
||||
}
|
||||
|
||||
fn load_language(
|
||||
loader: &FluentLanguageLoader,
|
||||
language: Language,
|
||||
) -> Result<(), i18n_embed::I18nEmbedError> {
|
||||
let mut requested = language.requested();
|
||||
if requested.is_empty() {
|
||||
requested.push(loader.fallback_language().clone());
|
||||
}
|
||||
i18n_embed::select(loader, &Localizations, &requested).map(|_| ())
|
||||
}
|
||||
|
||||
pub fn loader() -> &'static FluentLanguageLoader {
|
||||
static LOADER: OnceLock<FluentLanguageLoader> = OnceLock::new();
|
||||
LOADER.get_or_init(|| {
|
||||
let loader = fluent_language_loader!();
|
||||
if let Err(error) = load_language(&loader, Language::System) {
|
||||
eprintln!("Unable to load system UI language: {error}");
|
||||
loader
|
||||
.load_languages(&Localizations, &[loader.fallback_language().clone()])
|
||||
.expect("fallback UI language must be embedded");
|
||||
}
|
||||
loader
|
||||
})
|
||||
}
|
||||
|
||||
/// Apply a user preference process-wide. The loader swaps resources atomically,
|
||||
/// so the next Iced view pass immediately receives the new language.
|
||||
pub fn set_language(language: Language) -> Result<(), i18n_embed::I18nEmbedError> {
|
||||
load_language(loader(), language)
|
||||
}
|
||||
|
||||
/// Built-in ribbon modules have stable ids; plug-ins keep their supplied title
|
||||
/// until they provide their own localization bundle.
|
||||
pub fn ribbon_module_title(id: &str, fallback: &str) -> String {
|
||||
match id {
|
||||
"draw" => crate::tr!("ribbon-tab-draw"),
|
||||
"annotate" => crate::tr!("ribbon-tab-annotate"),
|
||||
"insert" => crate::tr!("ribbon-tab-insert"),
|
||||
"model" => crate::tr!("ribbon-tab-model"),
|
||||
"layout" => crate::tr!("ribbon-tab-layout"),
|
||||
"manage" => crate::tr!("ribbon-tab-manage"),
|
||||
"view" => crate::tr!("ribbon-tab-view"),
|
||||
_ => fallback.to_string(),
|
||||
}
|
||||
}
|
||||
|
||||
#[macro_export]
|
||||
macro_rules! tr {
|
||||
($message_id:literal $(,)?) => {
|
||||
i18n_embed_fl::fl!($crate::i18n::loader(), $message_id)
|
||||
};
|
||||
($message_id:literal, $($name:ident = $value:expr),+ $(,)?) => {
|
||||
i18n_embed_fl::fl!(
|
||||
$crate::i18n::loader(),
|
||||
$message_id,
|
||||
$($name = $value),+
|
||||
)
|
||||
};
|
||||
}
|
||||
|
|
@ -6,6 +6,7 @@ pub mod config;
|
|||
pub mod cli;
|
||||
pub mod command;
|
||||
pub mod entities;
|
||||
pub mod i18n;
|
||||
pub mod io;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
pub(crate) mod network;
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ mod config;
|
|||
mod cli;
|
||||
mod command;
|
||||
mod entities;
|
||||
mod i18n;
|
||||
mod io;
|
||||
#[cfg(not(target_arch = "wasm32"))]
|
||||
mod network;
|
||||
|
|
|
|||
|
|
@ -61,23 +61,27 @@ impl CadCommand for CopyCommand {
|
|||
|
||||
fn prompt(&self) -> String {
|
||||
if self.awaiting_count {
|
||||
return "COPY Enter number of items to array:".to_string();
|
||||
return crate::tr!("command-copy-array-count");
|
||||
}
|
||||
match &self.step {
|
||||
Step::Base => format!(
|
||||
"COPY Specify base point [{} objects]:",
|
||||
self.handles.len()
|
||||
Step::Base => crate::tr!(
|
||||
"command-copy-base",
|
||||
count = (self.handles.len() as i64),
|
||||
),
|
||||
Step::Placing(base) => {
|
||||
if let Some(n) = self.array_count {
|
||||
format!(
|
||||
"COPY Specify second point for {n}-item array [base {:.3},{:.3}]:",
|
||||
base.x, base.y
|
||||
crate::tr!(
|
||||
"command-copy-array-target",
|
||||
count = (n as i64),
|
||||
x = format!("{:.3}", base.x),
|
||||
y = format!("{:.3}", base.y),
|
||||
)
|
||||
} else {
|
||||
format!(
|
||||
"COPY Specify destination [{} copies so far | Array | Enter=done | base {:.3},{:.3}]:",
|
||||
self.count, base.x, base.y
|
||||
crate::tr!(
|
||||
"command-copy-target",
|
||||
count = (self.count as i64),
|
||||
x = format!("{:.3}", base.x),
|
||||
y = format!("{:.3}", base.y),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -53,13 +53,14 @@ impl CadCommand for MoveCommand {
|
|||
|
||||
fn prompt(&self) -> String {
|
||||
match &self.step {
|
||||
Step::Base => format!(
|
||||
"MOVE Specify base point [{} objects]:",
|
||||
self.handles.len()
|
||||
Step::Base => crate::tr!(
|
||||
"command-move-base",
|
||||
count = (self.handles.len() as i64),
|
||||
),
|
||||
Step::Target(base) => format!(
|
||||
"MOVE Specify destination [base {:.3},{:.3}]:",
|
||||
base.x, base.y
|
||||
Step::Target(base) => crate::tr!(
|
||||
"command-move-target",
|
||||
x = format!("{:.3}", base.x),
|
||||
y = format!("{:.3}", base.y),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -111,8 +111,8 @@ pub enum EntryKind {
|
|||
impl CommandLine {
|
||||
pub fn new() -> Self {
|
||||
let mut cl = Self::default();
|
||||
cl.push_info("Open CAD Studio ready.");
|
||||
cl.push_info("Type a command or use the ribbon. Open OBJ: INSERT tab.");
|
||||
cl.push_info(&crate::tr!("command-line-ready"));
|
||||
cl.push_info(&crate::tr!("command-line-hint"));
|
||||
cl
|
||||
}
|
||||
|
||||
|
|
@ -430,7 +430,7 @@ impl CommandLine {
|
|||
}
|
||||
});
|
||||
let prompt = container(
|
||||
text("Command:").size(11).style(|theme: &Theme| iced::widget::text::Style {
|
||||
text(crate::tr!("command-line-label")).size(11).style(|theme: &Theme| iced::widget::text::Style {
|
||||
color: Some(theme.palette().success.base.color),
|
||||
}),
|
||||
)
|
||||
|
|
@ -467,10 +467,7 @@ impl CommandLine {
|
|||
..Default::default()
|
||||
}
|
||||
});
|
||||
let literal_tip = container(
|
||||
text("Literal spaces: Space stays in the line instead of running the command (same as typing a leading '>'). Stays on until toggled off.")
|
||||
.size(11),
|
||||
)
|
||||
let literal_tip = container(text(crate::tr!("command-line-literal-spaces")).size(11))
|
||||
.padding([3, 6])
|
||||
.style(container::bordered_box);
|
||||
let literal_btn = tooltip(literal_btn, literal_tip, tooltip::Position::Top).gap(4);
|
||||
|
|
|
|||
|
|
@ -253,7 +253,7 @@ pub fn backdrop<'a>(
|
|||
/// title bar; pass `Vector::ZERO` to keep it centred.
|
||||
pub fn modal<'a>(
|
||||
base: impl Into<Element<'a, Message>>,
|
||||
title: &'a str,
|
||||
title: impl iced::widget::text::IntoFragment<'a>,
|
||||
content: impl Into<Element<'a, Message>>,
|
||||
on_close: Message,
|
||||
offset: Vector,
|
||||
|
|
|
|||
|
|
@ -422,7 +422,7 @@ impl Ribbon {
|
|||
let is_active = i == self.active;
|
||||
let is_contextual = module.id() == "layout";
|
||||
let btn = container(
|
||||
button(text(module.title()).size(12))
|
||||
button(text(crate::i18n::ribbon_module_title(module.id(), module.title())).size(12))
|
||||
.on_press(Message::RibbonSelectTab(i))
|
||||
.style(move |theme: &Theme, status| {
|
||||
let palette = theme.palette();
|
||||
|
|
|
|||
|
|
@ -9,6 +9,7 @@ pub fn view_window<'a>(
|
|||
default_save_format: &'a str,
|
||||
ui_theme: &'a UiThemeConfig,
|
||||
theme_color_inputs: &'a [String; 6],
|
||||
language: crate::i18n::Language,
|
||||
sizing: crate::ui::modal::ModalSizing,
|
||||
) -> Element<'a, Message> {
|
||||
let selected_format = crate::io::SAVE_FORMAT_OPTIONS
|
||||
|
|
@ -25,12 +26,12 @@ pub fn view_window<'a>(
|
|||
|
||||
let palette = ui_theme.palette.to_iced();
|
||||
let colors = [
|
||||
("Background", palette.background),
|
||||
("Text", palette.text),
|
||||
("Primary", palette.primary),
|
||||
("Success", palette.success),
|
||||
("Warning", palette.warning),
|
||||
("Danger", palette.danger),
|
||||
(crate::tr!("options-color-background"), palette.background),
|
||||
(crate::tr!("options-color-text"), palette.text),
|
||||
(crate::tr!("options-color-primary"), palette.primary),
|
||||
(crate::tr!("options-color-success"), palette.success),
|
||||
(crate::tr!("options-color-warning"), palette.warning),
|
||||
(crate::tr!("options-color-danger"), palette.danger),
|
||||
];
|
||||
|
||||
let mut color_controls = column![].spacing(8);
|
||||
|
|
@ -60,16 +61,31 @@ pub fn view_window<'a>(
|
|||
);
|
||||
}
|
||||
|
||||
let close = button(text("Close").size(12))
|
||||
let close = button(text(crate::tr!("action-close")).size(12))
|
||||
.on_press(Message::CloseModal)
|
||||
.padding([6, 18])
|
||||
.style(button::secondary);
|
||||
|
||||
let content = column![
|
||||
text("Open and Save").size(15),
|
||||
text(crate::tr!("options-language-section")).size(15),
|
||||
Space::new().height(10),
|
||||
row![
|
||||
text("Default save format:").size(12).width(150),
|
||||
text(crate::tr!("options-language-label")).size(12).width(150),
|
||||
iced::widget::pick_list(
|
||||
Some(language),
|
||||
crate::i18n::Language::ALL,
|
||||
|value| value.to_string(),
|
||||
)
|
||||
.on_select(Message::LanguageChanged)
|
||||
.width(sizing.width),
|
||||
]
|
||||
.spacing(12)
|
||||
.align_y(iced::Center),
|
||||
Space::new().height(22),
|
||||
text(crate::tr!("options-open-save-section")).size(15),
|
||||
Space::new().height(10),
|
||||
row![
|
||||
text(crate::tr!("options-default-save-format-label")).size(12).width(150),
|
||||
iced::widget::pick_list(
|
||||
selected_format,
|
||||
crate::io::SAVE_FORMAT_OPTIONS,
|
||||
|
|
@ -81,16 +97,14 @@ pub fn view_window<'a>(
|
|||
.spacing(12)
|
||||
.align_y(iced::Center),
|
||||
Space::new().height(8),
|
||||
text(
|
||||
"Used for the first save of a new drawing. Existing drawings keep their file type and version."
|
||||
)
|
||||
text(crate::tr!("options-default-save-format-help"))
|
||||
.size(11)
|
||||
.width(sizing.width),
|
||||
Space::new().height(22),
|
||||
text("Theme").size(15),
|
||||
text(crate::tr!("options-theme-section")).size(15),
|
||||
Space::new().height(10),
|
||||
row![
|
||||
text("Iced theme:").size(12).width(150),
|
||||
text(crate::tr!("options-theme-label")).size(12).width(150),
|
||||
iced::widget::pick_list(
|
||||
selected_theme,
|
||||
theme_options,
|
||||
|
|
@ -102,9 +116,7 @@ pub fn view_window<'a>(
|
|||
.spacing(12)
|
||||
.align_y(iced::Center),
|
||||
Space::new().height(8),
|
||||
text(
|
||||
"Changing a base colour switches to Custom. Iced generates every component shade from these six colours."
|
||||
)
|
||||
text(crate::tr!("options-theme-help"))
|
||||
.size(11)
|
||||
.width(sizing.width),
|
||||
Space::new().height(12),
|
||||
|
|
|
|||
Loading…
Reference in a new issue