Added support for localization, with English and French translations (#25).

This commit is contained in:
Antoine POPINEAU 2021-06-24 08:41:10 +02:00
parent 0b21921b4d
commit f618d16559
No known key found for this signature in database
GPG Key ID: A78AC64694F84063
14 changed files with 637 additions and 41 deletions

492
Cargo.lock generated
View File

@ -1,5 +1,11 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "Inflector"
version = "0.11.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3"
[[package]]
name = "ahash"
version = "0.4.7"
@ -27,6 +33,12 @@ version = "1.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf1de2fe8c75bc145a2f577add951f8134889b4795d47466a54a5c846d691693"
[[package]]
name = "block"
version = "0.1.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a"
[[package]]
name = "cassowary"
version = "0.3.0"
@ -60,10 +72,21 @@ dependencies = [
"libc",
"num-integer",
"num-traits",
"pure-rust-locales",
"time",
"winapi",
]
[[package]]
name = "dashmap"
version = "4.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e77a43b28d0668df09411cb0bc9a8c2adc40f9a048afe863e05fd43251e8e39c"
dependencies = [
"cfg-if 1.0.0",
"num_cpus",
]
[[package]]
name = "dlv-list"
version = "0.2.2"
@ -73,6 +96,59 @@ dependencies = [
"rand",
]
[[package]]
name = "find-crate"
version = "0.6.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "59a98bbaacea1c0eb6a0876280051b892eb73594fd90cf3b20e9c817029c57d2"
dependencies = [
"toml",
]
[[package]]
name = "fluent"
version = "0.15.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bc4d7142005e2066e4844caf9f271b93fc79836ee96ec85057b8c109687e629a"
dependencies = [
"fluent-bundle",
"unic-langid",
]
[[package]]
name = "fluent-bundle"
version = "0.15.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8acf044eeb4872d9dbf2667541fbf461f5965c57e343878ad0fb24b5793fa007"
dependencies = [
"fluent-langneg",
"fluent-syntax",
"intl-memoizer",
"intl_pluralrules",
"ouroboros",
"rustc-hash",
"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 = "getopts"
version = "0.2.21"
@ -113,18 +189,171 @@ dependencies = [
"ahash",
]
[[package]]
name = "hermit-abi"
version = "0.1.18"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "322f4de77956e22ed0e5032c359a0f1273f1f7f0d79bfa3b8ffbc730d7fbcc5c"
dependencies = [
"libc",
]
[[package]]
name = "i18n-config"
version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b62affcd43abfb51f3cbd8736f9407908dc5b44fc558a9be07460bbfd104d983"
dependencies = [
"log",
"serde",
"serde_derive",
"thiserror",
"toml",
"unic-langid",
]
[[package]]
name = "i18n-embed"
version = "0.12.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3794c3d7fea43e076281c9213cfaaa7a53c3f18b1613f12514b9f575a2908457"
dependencies = [
"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.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4d91f4951bd0bc19624a06781bf8cd05bdd59057622e5d4240823b42a5f102d2"
dependencies = [
"dashmap",
"find-crate",
"fluent",
"fluent-syntax",
"i18n-config",
"i18n-embed",
"lazy_static",
"proc-macro-error",
"proc-macro2",
"quote",
"strsim",
"syn",
"unic-langid",
]
[[package]]
name = "i18n-embed-impl"
version = "0.7.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2757ae6d1dd47fba009e86795350186fc4740a6e53a1b4f336a8a6725d20eb53"
dependencies = [
"find-crate",
"i18n-config",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "instant"
version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "61124eeebbd69b8190558df225adf7e4caafce0d743919e5d6b19652314ec5ec"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "intl-memoizer"
version = "0.5.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f"
dependencies = [
"type-map",
"unic-langid",
]
[[package]]
name = "intl_pluralrules"
version = "7.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b18f988384267d7066cc2be425e6faf352900652c046b6971d2e228d3b1c5ecf"
dependencies = [
"tinystr",
"unic-langid",
]
[[package]]
name = "itoa"
version = "0.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dc6f3ad7b9d11a0c00842ff8de1b60ee58661048eb8049ed33c73594f359d7e6"
[[package]]
name = "lazy_static"
version = "1.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
[[package]]
name = "libc"
version = "0.2.95"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "789da6d93f1b866ffe175afc5322a4d76c038605a1c3319bb57b06967ca98a36"
[[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.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0382880606dff6d15c9476c416d18690b72742aa7b605bb6dd6ec9030fbf07eb"
dependencies = [
"scopeguard",
]
[[package]]
name = "log"
version = "0.4.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710"
dependencies = [
"cfg-if 1.0.0",
]
[[package]]
name = "malloc_buf"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "62bb907fe88d54d8d9ce32a3cceab4218ed2f6b7d35617cafe9adf84e43919cb"
dependencies = [
"libc",
]
[[package]]
name = "memchr"
version = "2.4.0"
@ -172,12 +401,51 @@ dependencies = [
"autocfg",
]
[[package]]
name = "num_cpus"
version = "1.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "05499f3756671c15885fee9034446956fff3f243d6077b91e5767df161f766b3"
dependencies = [
"hermit-abi",
"libc",
]
[[package]]
name = "numtoa"
version = "0.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8f8bdf33df195859076e54ab11ee78a1b208382d3a26ec40d142ffc1ecc49ef"
[[package]]
name = "objc"
version = "0.2.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "915b1b472bc21c53464d6c8461c9d3af805ba1ef837e1cac254428f4a77177b1"
dependencies = [
"malloc_buf",
]
[[package]]
name = "objc-foundation"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1add1b659e36c9607c7aab864a76c7a4c2760cd0cd2e120f3fb8b952c7e22bf9"
dependencies = [
"block",
"objc",
"objc_id",
]
[[package]]
name = "objc_id"
version = "0.1.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c92d4ddb4bd7b50d730c215ff871754d0da6b2178849f8a2a2ab69712d0c073b"
dependencies = [
"objc",
]
[[package]]
name = "ordered-multimap"
version = "0.3.1"
@ -188,12 +456,84 @@ dependencies = [
"hashbrown",
]
[[package]]
name = "ouroboros"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cc1f52300b81ac4eeeb6c00c20f7e86556c427d9fb2d92b68fc73c22f331cd15"
dependencies = [
"ouroboros_macro",
"stable_deref_trait",
]
[[package]]
name = "ouroboros_macro"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "41db02c8f8731cdd7a72b433c7900cce4bf245465b452c364bfd21f4566ab055"
dependencies = [
"Inflector",
"proc-macro-error",
"proc-macro2",
"quote",
"syn",
]
[[package]]
name = "parking_lot"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "6d7744ac029df22dca6284efe4e898991d28e3085c706c972bcd7da4a27a15eb"
dependencies = [
"instant",
"lock_api",
"parking_lot_core",
]
[[package]]
name = "parking_lot_core"
version = "0.8.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fa7a782938e745763fe6907fc6ba86946d72f49fe7e21de074e08128a99fb018"
dependencies = [
"cfg-if 1.0.0",
"instant",
"libc",
"redox_syscall 0.2.8",
"smallvec",
"winapi",
]
[[package]]
name = "ppv-lite86"
version = "0.2.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "237a5ed80e274dbc66f86bd59c1e25edc039660be53194b5fe0a482e0f2612ea"
[[package]]
name = "proc-macro-error"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c"
dependencies = [
"proc-macro-error-attr",
"proc-macro2",
"quote",
"syn",
"version_check",
]
[[package]]
name = "proc-macro-error-attr"
version = "1.0.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869"
dependencies = [
"proc-macro2",
"quote",
"version_check",
]
[[package]]
name = "proc-macro2"
version = "1.0.19"
@ -203,6 +543,12 @@ dependencies = [
"unicode-xid",
]
[[package]]
name = "pure-rust-locales"
version = "0.5.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b45c49fc4f91f35bae654f85ebb3a44d60ac64f11b3166ffa609def390c732d8"
[[package]]
name = "quote"
version = "1.0.7"
@ -294,6 +640,39 @@ version = "0.6.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f497285884f3fcff424ffc933e56d7cbca511def0c9831a7f9b5f6153e3cc89b"
[[package]]
name = "rust-embed"
version = "5.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2fe1fe6aac5d6bb9e1ffd81002340363272a7648234ec7bdfac5ee202cb65523"
dependencies = [
"rust-embed-impl",
"rust-embed-utils",
"walkdir",
]
[[package]]
name = "rust-embed-impl"
version = "5.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3ed91c41c42ef7bf687384439c312e75e0da9c149b0390889b94de3c7d9d9e66"
dependencies = [
"proc-macro2",
"quote",
"rust-embed-utils",
"syn",
"walkdir",
]
[[package]]
name = "rust-embed-utils"
version = "5.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2a512219132473ab0a77b52077059f1c47ce4af7fbdc94503e9862a34422876d"
dependencies = [
"walkdir",
]
[[package]]
name = "rust-ini"
version = "0.17.0"
@ -304,12 +683,33 @@ dependencies = [
"ordered-multimap",
]
[[package]]
name = "rustc-hash"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
[[package]]
name = "ryu"
version = "1.0.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "71d301d4193d031abdd79ff7e3dd721168a9572ef3fe51a1517aba235bd8f86e"
[[package]]
name = "same-file"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "93fc1dc3aaa9bfed95e02e6eadabb4baf7e3078b0bd1b4d7b6b0b68378900502"
dependencies = [
"winapi-util",
]
[[package]]
name = "scopeguard"
version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "d29ab0c6d3fc0ee92fe66e2d99f700eab17a8d57d1c1d3b748380fb20baa78cd"
[[package]]
name = "serde"
version = "1.0.115"
@ -341,12 +741,30 @@ dependencies = [
"serde",
]
[[package]]
name = "smallvec"
version = "1.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fe0f37c9e8f3c5a4a66ad655a93c74daac4ad00c441533bf5c6e7990bb42604e"
[[package]]
name = "smawk"
version = "0.3.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f67ad224767faa3c7d8b6d91985b78e70a1324408abcb1cfcc2be4c06bc06043"
[[package]]
name = "stable_deref_trait"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]]
name = "syn"
version = "1.0.38"
@ -420,6 +838,21 @@ dependencies = [
"winapi",
]
[[package]]
name = "tinystr"
version = "0.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "29738eedb4388d9ea620eeab9384884fc3f06f586a2eddb56bedc5885126c7c1"
[[package]]
name = "toml"
version = "0.5.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa"
dependencies = [
"serde",
]
[[package]]
name = "tui"
version = "0.15.0"
@ -440,15 +873,48 @@ dependencies = [
"chrono",
"getopts",
"greetd_ipc",
"i18n-embed",
"i18n-embed-fl",
"lazy_static",
"nix",
"rust-embed",
"rust-ini",
"system_shutdown",
"termion",
"textwrap",
"tui",
"unic-langid",
"zeroize",
]
[[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 = "unic-langid"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73328fcd730a030bdb19ddf23e192187a6b01cd98be6d3140622a89129459ce5"
dependencies = [
"unic-langid-impl",
]
[[package]]
name = "unic-langid-impl"
version = "0.9.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1a4a8eeaf0494862c1404c95ec2f4c33a2acff5076f64314b465e3ddae1b934d"
dependencies = [
"serde",
"tinystr",
]
[[package]]
name = "unicode-linebreak"
version = "0.1.1"
@ -476,6 +942,23 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "version_check"
version = "0.9.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5fecdca9a5291cc2b8dcf7dc02453fee791a280f3743cb0905f8822ae463b3fe"
[[package]]
name = "walkdir"
version = "2.3.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "808cf2735cd4b6866113f648b791c6adc5714537bc222d9347bb203386ffda56"
dependencies = [
"same-file",
"winapi",
"winapi-util",
]
[[package]]
name = "wasi"
version = "0.9.0+wasi-snapshot-preview1"
@ -498,6 +981,15 @@ version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-util"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "70ec6ce85bb158151cae5e5c87f95a8e97d2c0c4b001223f33a334e3ce5de178"
dependencies = [
"winapi",
]
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"

View File

@ -8,14 +8,19 @@ build = "build.rs"
[dependencies]
getopts = "0.2.21"
greetd_ipc = { version = "0.6.0", features = ["sync-codec"] }
i18n-embed = { version = "0.12.1", features = ["desktop-requester", "fluent-system"] }
i18n-embed-fl = "0.5.0"
lazy_static = "1.4.0"
termion = "1.5.6"
tui = "0.15.0"
nix = "0.21.0"
textwrap = "0.14.0"
chrono = "0.4.19"
chrono = { version = "0.4.19", features = ["unstable-locales"] }
zeroize = "1.3.0"
rust-embed = "5"
rust-ini = "0.17.0"
system_shutdown = "3.0.0"
unic-langid = "0.9"
[profile.release]
lto = true

View File

@ -0,0 +1,22 @@
title_authenticate = Authenticate into {$hostname}
title_command = Change session command
title_power = Power options
title_session = Change session
action_reset = Reset
action_command = Change command
action_session = Choose session
action_power = Power
date = %a, %d %h %Y - %H:%M
username = Username:
wait = Please wait...
new_command = New command:
shutdown = Shut down
reboot = Reboot
status_command = CMD
status_caps = CAPS LOCK

View File

@ -0,0 +1,22 @@
title_authenticate = Se connecter à {$hostname}
title_command = Changer la commande de session
title_power = Options d'alimentation
title_session = Changer la session
action_reset = RAZ
action_command = Changer la commande
action_session = Choisir la session
action_power = Alimentation
date = %a %d %h %Y - %H:%M
username = Nom d'utilisateur :
wait = Veillez patienter...
command = Nouvelle commande :
shutdown = Eteindre
reboot = Redémarrer
status_command = CMD
status_caps = VERR. MAJ.

4
i18n.toml Normal file
View File

@ -0,0 +1,4 @@
fallback_language = "en-US"
[fluent]
assets_dir = "contrib/locales"

View File

@ -1,4 +1,5 @@
use std::{
convert::TryInto,
env,
error::Error,
fmt::{self, Display},
@ -6,8 +7,10 @@ use std::{
process,
};
use chrono::Locale;
use getopts::{Matches, Options};
use greetd_ipc::Request;
use i18n_embed::DesktopLanguageRequester;
use zeroize::Zeroize;
use crate::info::{get_issue, get_last_username};
@ -44,6 +47,7 @@ impl Default for Mode {
#[derive(Default)]
pub struct Greeter {
pub locale: Option<Locale>,
pub config: Option<Matches>,
pub socket: String,
pub stream: Option<UnixStream>,
@ -88,6 +92,7 @@ impl Greeter {
pub fn new() -> Self {
let mut greeter = Self::default();
greeter.set_locale();
greeter.parse_options();
greeter.sessions = crate::info::get_sessions(&greeter).unwrap_or_default();
greeter.selected_session = greeter.sessions.iter().position(|(_, command)| Some(command) == greeter.command.as_ref()).unwrap_or(0);
@ -173,7 +178,18 @@ impl Greeter {
1
}
pub fn parse_options(&mut self) {
fn set_locale(&mut self) {
self.locale = match DesktopLanguageRequester::requested_languages().into_iter().next() {
Some(selected) => match selected.region {
None => None,
Some(region) => format!("{}_{}", selected.language, region).as_str().try_into().ok(),
},
None => None,
};
}
fn parse_options(&mut self) {
let mut opts = Options::new();
opts.optflag("h", "help", "show this usage information");

9
src/macros.rs Normal file
View File

@ -0,0 +1,9 @@
macro_rules! fl {
($message_id:literal) => {{
i18n_embed_fl::fl!($crate::MESSAGES, $message_id)
}};
($message_id:literal, $($args:expr),*) => {{
i18n_embed_fl::fl!($crate::MESSAGES, $message_id, $($args), *)
}};
}

View File

@ -3,17 +3,41 @@ mod event;
mod info;
mod ipc;
mod keyboard;
#[macro_use]
mod macros;
mod ui;
use std::{error::Error, io, process};
use greetd_ipc::Request;
use i18n_embed::{
fluent::{fluent_language_loader, FluentLanguageLoader},
DesktopLanguageRequester, LanguageLoader,
};
use lazy_static::lazy_static;
use rust_embed::RustEmbed;
use termion::raw::IntoRawMode;
use tui::{backend::TermionBackend, Terminal};
pub use self::config::*;
use self::event::Events;
#[derive(RustEmbed)]
#[folder = "contrib/locales"]
struct Localizations;
lazy_static! {
static ref MESSAGES: FluentLanguageLoader = {
let locales = Localizations;
let loader = fluent_language_loader!();
loader.load_languages(&locales, &[loader.fallback_language()]).unwrap();
let _ = i18n_embed::select(&loader, &locales, &DesktopLanguageRequester::requested_languages());
loader
};
}
fn main() {
if let Err(error) = run() {
if let Some(AuthStatus::Success) = error.downcast_ref::<AuthStatus>() {

View File

@ -12,9 +12,6 @@ use tui::{
use super::prompt_value;
use crate::{ui::util::*, Greeter};
const CHANGE_COMMAND: &str = " Change session command ";
const COMMAND: &str = "New command:";
pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::Stdout>>>) -> Result<(u16, u16), Box<dyn Error>> {
let size = f.size();
@ -27,7 +24,7 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
let container = Rect::new(x, y, width, height);
let frame = Rect::new(x + container_padding, y + container_padding, width - container_padding, height - container_padding);
let block = Block::default().title(CHANGE_COMMAND).borders(Borders::ALL).border_type(BorderType::Plain);
let block = Block::default().title(titleize(&fl!("title_command"))).borders(Borders::ALL).border_type(BorderType::Plain);
f.render_widget(block, container);
@ -38,15 +35,18 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
let chunks = Layout::default().direction(Direction::Vertical).constraints(constraints.as_ref()).split(frame);
let cursor = chunks[0];
let command_label_text = prompt_value(COMMAND);
let command_label_text = prompt_value(fl!("new_command"));
let command_label = Paragraph::new(command_label_text);
let command_value_text = Span::from(greeter.new_command.clone());
let command_value = Paragraph::new(command_value_text);
f.render_widget(command_label, chunks[0]);
f.render_widget(command_value, Rect::new(1 + chunks[0].x + COMMAND.len() as u16, chunks[0].y, get_input_width(greeter, COMMAND), 1));
f.render_widget(
command_value,
Rect::new(1 + chunks[0].x + fl!("new_command").len() as u16, chunks[0].y, get_input_width(greeter, &fl!("new_command")), 1),
);
let offset = get_cursor_offset(greeter, greeter.new_command.chars().count());
Ok((2 + cursor.x + COMMAND.len() as u16 + offset as u16, cursor.y + 1))
Ok((2 + cursor.x + fl!("new_command").len() as u16 + offset as u16, cursor.y + 1))
}

View File

@ -24,13 +24,6 @@ use crate::{info::capslock_status, Greeter, Mode};
pub use self::power::{Option as PowerOption, OPTIONS as POWER_OPTIONS};
const RESET: &str = "Reset";
const SESSIONS: &str = "Choose session";
const CHANGE_COMMAND: &str = "Change command";
const COMMAND: &str = "COMMAND";
const POWER: &str = "POWER";
const CAPS_LOCK: &str = "CAPS LOCK";
const TITLEBAR_INDEX: usize = 1;
const STATUSBAR_INDEX: usize = 3;
const STATUSBAR_LEFT_INDEX: usize = 1;
@ -60,7 +53,7 @@ pub fn draw(terminal: &mut Terminal<TermionBackend<RawTerminal<io::Stdout>>>, gr
.split(size);
if greeter.config().opt_present("time") {
let time_text = Span::from(get_time());
let time_text = Span::from(get_time(&greeter));
let time = Paragraph::new(time_text).alignment(Alignment::Center);
f.render_widget(time, chunks[TITLEBAR_INDEX]);
@ -82,14 +75,14 @@ pub fn draw(terminal: &mut Terminal<TermionBackend<RawTerminal<io::Stdout>>>, gr
let command = greeter.command.clone().unwrap_or_else(|| "-".to_string());
let status_left_text = Spans::from(vec![
status_label("ESC"),
status_value(RESET),
status_value(fl!("action_reset")),
status_label("F2"),
status_value(CHANGE_COMMAND),
status_value(fl!("action_command")),
status_label("F3"),
status_value(SESSIONS),
status_value(fl!("action_session")),
status_label("F12"),
status_value(POWER),
status_label(COMMAND),
status_value(fl!("action_power")),
status_label(fl!("status_command")),
status_value(command),
]);
let status_left = Paragraph::new(status_left_text);
@ -97,7 +90,7 @@ pub fn draw(terminal: &mut Terminal<TermionBackend<RawTerminal<io::Stdout>>>, gr
f.render_widget(status_left, status_chunks[STATUSBAR_LEFT_INDEX]);
if capslock_status() {
let status_right_text = status_label(format!(" {} ", CAPS_LOCK));
let status_right_text = status_label(fl!("status_caps"));
let status_right = Paragraph::new(status_right_text).alignment(Alignment::Right);
f.render_widget(status_right, status_chunks[STATUSBAR_RIGHT_INDEX]);
@ -122,8 +115,8 @@ pub fn draw(terminal: &mut Terminal<TermionBackend<RawTerminal<io::Stdout>>>, gr
Ok(())
}
fn get_time() -> String {
Local::now().format("%a, %d %h %Y - %H:%M").to_string()
fn get_time(greeter: &Greeter) -> String {
Local::now().format_localized(&fl!("date"), greeter.locale.unwrap_or(Locale::en_US)).to_string()
}
fn status_label<'s, S>(text: S) -> Span<'s>

View File

@ -1,5 +1,6 @@
use std::{error::Error, io};
use lazy_static::lazy_static;
use termion::raw::RawTerminal;
use tui::{
backend::TermionBackend,
@ -13,14 +14,19 @@ use tui::{
use super::util::*;
use crate::Greeter;
const TITLE: &str = "Power options";
pub enum Option {
Shutdown,
Reboot,
}
pub const OPTIONS: &[(Option, &str)] = &[(Option::Shutdown, "Shutdown"), (Option::Reboot, "Reboot")];
lazy_static! {
pub static ref OPTIONS: [(Option, String); 2] = {
let shutdown = fl!("shutdown");
let reboot = fl!("reboot");
[(Option::Shutdown, shutdown), (Option::Reboot, reboot)]
};
}
pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::Stdout>>>) -> Result<(u16, u16), Box<dyn Error>> {
let size = f.size();
@ -32,7 +38,7 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
let container = Rect::new(x, y, width, height);
let title = Span::from(format!(" {} ", TITLE));
let title = Span::from(titleize(&fl!("title_power")));
let block = Block::default().title(title).borders(Borders::ALL).border_type(BorderType::Plain);
for (index, (_, label)) in OPTIONS.iter().enumerate() {

View File

@ -17,10 +17,6 @@ const USERNAME_INDEX: usize = 1;
const ANSWER_INDEX: usize = 2;
const MESSAGE_INDEX: usize = 3;
const TITLE: &str = "Authenticate into";
const USERNAME: &str = "Username:";
const WORKING: &str = "Please wait...";
pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::Stdout>>>) -> Result<(u16, u16), Box<dyn Error>> {
let size = f.size();
@ -34,7 +30,7 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
let container = Rect::new(x, y, width, height);
let frame = Rect::new(x + container_padding, y + container_padding, width - (2 * container_padding), height - (2 * container_padding));
let hostname = Span::from(format!(" {} {} ", TITLE, get_hostname()));
let hostname = Span::from(titleize(&fl!("title_authenticate", hostname = get_hostname())));
let block = Block::default().title(hostname).borders(Borders::ALL).border_type(BorderType::Plain);
f.render_widget(block, container);
@ -62,7 +58,7 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
f.render_widget(greeting_label, chunks[GREETING_INDEX]);
}
let username_text = prompt_value(USERNAME);
let username_text = prompt_value(fl!("username"));
let username_label = Paragraph::new(username_text);
let username_value_text = Span::from(greeter.username.clone());
@ -73,10 +69,15 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
f.render_widget(username_label, chunks[USERNAME_INDEX]);
f.render_widget(
username_value,
Rect::new(1 + chunks[USERNAME_INDEX].x + USERNAME.len() as u16, chunks[USERNAME_INDEX].y, get_input_width(greeter, USERNAME), 1),
Rect::new(
1 + chunks[USERNAME_INDEX].x + fl!("username").len() as u16,
chunks[USERNAME_INDEX].y,
get_input_width(greeter, &fl!("username")),
1,
),
);
let answer_text = if greeter.working { Span::from(WORKING) } else { prompt_value(&greeter.prompt) };
let answer_text = if greeter.working { Span::from(fl!("wait")) } else { prompt_value(&greeter.prompt) };
let answer_label = Paragraph::new(answer_text);
if greeter.mode == Mode::Password || greeter.previous_mode == Mode::Password {
@ -123,7 +124,7 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
Mode::Username => {
let offset = get_cursor_offset(greeter, greeter.username.chars().count());
Ok((2 + cursor.x + USERNAME.len() as u16 + offset as u16, USERNAME_INDEX as u16 + cursor.y))
Ok((2 + cursor.x + fl!("username").len() as u16 + offset as u16, USERNAME_INDEX as u16 + cursor.y))
}
Mode::Password => {

View File

@ -13,8 +13,6 @@ use tui::{
use super::util::*;
use crate::Greeter;
const CHANGE_SESSION: &str = "Change session";
pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::Stdout>>>) -> Result<(u16, u16), Box<dyn Error>> {
let size = f.size();
@ -25,7 +23,7 @@ pub fn draw(greeter: &mut Greeter, f: &mut Frame<TermionBackend<RawTerminal<io::
let container = Rect::new(x, y, width, height);
let title = Span::from(format!(" {} ", CHANGE_SESSION));
let title = Span::from(titleize(&fl!("title_session")));
let block = Block::default().title(title).borders(Borders::ALL).border_type(BorderType::Plain);
for (index, (name, _)) in greeter.sessions.iter().enumerate() {

View File

@ -1,5 +1,9 @@
use crate::{Greeter, Mode};
pub fn titleize(message: &str) -> String {
format!(" {} ", message)
}
pub fn get_height(greeter: &Greeter) -> u16 {
let container_padding = greeter.container_padding();
let prompt_padding = greeter.prompt_padding();