From 06849fe6683a3dd176673ac130c4da135abb49b9 Mon Sep 17 00:00:00 2001 From: Dorota Czaplejewicz Date: Wed, 20 Nov 2019 21:35:20 +0000 Subject: [PATCH] language: Use dbus to find out current language before env --- Cargo.lock | 20 ++++++++++++++ Cargo.toml | 1 + debian/control | 1 + src/lib.rs | 1 + src/locale_config.rs | 65 ++++++++++++++++++++++++++++++++++---------- src/meson.build | 1 + src/popover.rs | 13 ++++----- 7 files changed, 79 insertions(+), 23 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bb1d07ef..cd485c1a 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -54,6 +54,15 @@ name = "cc" version = "1.0.45" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "dbus" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)", + "libdbus-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "dtoa" version = "0.4.4" @@ -232,6 +241,14 @@ name = "libc" version = "0.2.62" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "libdbus-sys" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "pkg-config 0.3.16 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "linked-hash-map" version = "0.5.2" @@ -324,6 +341,7 @@ name = "rs" version = "0.1.0" dependencies = [ "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "dbus 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", "gio 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)", "glib 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "glib-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -436,6 +454,7 @@ dependencies = [ "checksum cairo-rs 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "dd940f0d609699e343ef71c4af5f66423afbf30d666f796dabd8fd15229cf5b6" "checksum cairo-sys-rs 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d25596627380be4381247dba06c69ad05ca21b3b065bd9827e416882ac41dcd2" "checksum cc 1.0.45 (registry+https://github.com/rust-lang/crates.io-index)" = "4fc9a35e1f4290eb9e5fc54ba6cf40671ed2a2514c3eeb2b2a908dda2ea5a1be" +"checksum dbus 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)" = "48b5f0f36f1eebe901b0e6bee369a77ed3396334bf3f09abd46454a576f71819" "checksum dtoa 0.4.4 (registry+https://github.com/rust-lang/crates.io-index)" = "ea57b42383d091c85abcc2706240b94ab2a8fa1fc81c10ff23c4de06e2a90b5e" "checksum fragile 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "05f8140122fa0d5dcb9fc8627cfce2b37cc1500f752636d46ea28bc26785c2f9" "checksum gdk 0.9.0 (registry+https://github.com/rust-lang/crates.io-index)" = "bcc52c7244046df9d959df87289f1fc5cca23f9f850bab0c967963e2ecb83a96" @@ -451,6 +470,7 @@ dependencies = [ "checksum gtk-sys 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d487d333a4b87072e6bf9f2e55befa0ebef01b9496c2e263c0f4a1ff3d6c04b1" "checksum lazy_static 1.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646" "checksum libc 0.2.62 (registry+https://github.com/rust-lang/crates.io-index)" = "34fcd2c08d2f832f376f4173a231990fa5aef4e99fb569867318a227ef4c06ba" +"checksum libdbus-sys 0.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "dc12a3bc971424edbbf7edaf6e5740483444db63aa8e23d3751ff12a30f306f0" "checksum linked-hash-map 0.5.2 (registry+https://github.com/rust-lang/crates.io-index)" = "ae91b68aebc4ddb91978b11a1b02ddd8602a05ec19002801c5666000e05e0f83" "checksum maplit 1.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "3e2e65a1a2e43cfcb47a895c4c8b10d1f4a61097f9f254f183aee60cad9c651d" "checksum memchr 2.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "88579771288728879b57485cc7d6b07d648c9f0141eb955f8ab7f9d45394468e" diff --git a/Cargo.toml b/Cargo.toml index b7fbd203..f3ba5e03 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" [dependencies] bitflags = "1.0.*" +dbus = "0.6.*" maplit = "1.0.*" regex = "1.1.*" serde = { version = "1.0.*", features = ["derive"] } diff --git a/debian/control b/debian/control index 69615a26..7e081df4 100644 --- a/debian/control +++ b/debian/control @@ -12,6 +12,7 @@ Build-Depends: libgtk-3-dev, libcroco3-dev, librust-bitflags-1-dev (>= 1.0), + librust-dbus-0.6-dev (>= 0.6), librust-gio+v2-44-dev, librust-glib+v2-44-dev, librust-glib-sys-dev, diff --git a/src/lib.rs b/src/lib.rs index 21bfde8a..d8bdfa4a 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,5 +1,6 @@ #[macro_use] extern crate bitflags; +extern crate dbus; extern crate gio; extern crate glib; extern crate glib_sys; diff --git a/src/locale_config.rs b/src/locale_config.rs index 0595f2b7..1a3af59c 100644 --- a/src/locale_config.rs +++ b/src/locale_config.rs @@ -1,8 +1,8 @@ /*! Locale detection and management. * Based on https://github.com/rust-locale/locale_config * - * Ready for deletion/replacement once Debian starts packaging this, - * although this version doesn't need lazy_static. + * Modified for dbus querying. + * This version doesn't need lazy_static. * * Copyright (c) 2016–2019 Jan Hudec Copyright (c) 2016 A.J. Gardner @@ -11,10 +11,13 @@ Copyright (c) 2019, Sophie Tauchert <999eagle@999eagle.moe> */ +use dbus::Connection; use regex::Regex; use std::borrow::Cow; use std::env; +use dbus::stdintf::org_freedesktop_dbus::Properties; + /// Errors that may be returned by `locale_config`. #[derive(Copy,Clone,Debug,PartialEq,Eq)] pub enum Error { @@ -463,19 +466,23 @@ fn tag(s: &str) -> Result { // TODO: Read /etc/locale.alias fn tag_inv(s: &str) -> LanguageRange { - tag(s).unwrap_or(LanguageRange::invariant()) + tag(s).unwrap_or_else(|_e| LanguageRange::invariant()) } -pub fn system_locale() -> Option { +/// Returns the locale using Unix roles and the given lookup method. +// TODO: maybe don't drop all errors on the floor like that +fn unix_locale<'a, 'b, F, E>(get: F) -> Locale + where F: Fn(&'a str) -> ::std::result::Result +{ // LC_ALL overrides everything - if let Ok(all) = env::var("LC_ALL") { + if let Ok(all) = get("LC_ALL") { if let Ok(t) = tag(all.as_ref()) { - return Some(Locale::from(t)); + return Locale::from(t); } } // LANG is default let mut loc = - if let Ok(lang) = env::var("LANG") { + if let Ok(lang) = get("LANG") { Locale::from(tag_inv(lang.as_ref())) } else { Locale::invariant() @@ -494,7 +501,7 @@ pub fn system_locale() -> Option { ("telephone", "LC_TELEPHONE"), ("measurement", "LC_MEASUREMENT"), ].iter() { - if let Ok(val) = env::var(var) { + if let Ok(val) = get(var) { if let Ok(tag) = tag(val.as_ref()) { loc.add_category(cat, &tag); @@ -502,7 +509,7 @@ pub fn system_locale() -> Option { } } // LANGUAGE defines fallbacks - if let Ok(langs) = env::var("LANGUAGE") { + if let Ok(langs) = get("LANGUAGE") { for i in langs.split(':') { if i != "" { if let Ok(tag) = tag(i) { @@ -511,16 +518,44 @@ pub fn system_locale() -> Option { } } } - if loc.as_ref() != "" { - return Some(loc); - } else { - return None; - } + + loc +} + +fn env_locale() -> Locale { + unix_locale(env::var) +} + +fn dbus_locale() + -> std::result::Result> +{ + let connection = Connection::get_private(dbus::BusType::Session)?; + let property = connection.with_path( + "org.freedesktop.locale1", "/org/freedesktop/locale1", 100 + ); + let locales: Vec + = property.get("org.freedesktop.locale1", "Locale")?; + + let val_pairs: Vec<(String, String)> = locales.into_iter().map(|s| { + let mut splits = s.splitn(2, "="); + (splits.next().unwrap().into(), splits.next().unwrap_or("").into()) + }).collect(); + + Ok(unix_locale(|var| { + match val_pairs.iter().find(|(name, _val)| name == &var) { + Some((_name, val)) => Ok(val.clone()), + None => Err(()), + } + })) +} + +pub fn system_locale() -> Locale { + dbus_locale().unwrap_or_else(|_e| env_locale()) } #[cfg(test)] mod test { - use super::LanguageRange; + use super::*; #[test] fn unix_tags() { diff --git a/src/meson.build b/src/meson.build index e1a98ab9..edbc6911 100644 --- a/src/meson.build +++ b/src/meson.build @@ -39,6 +39,7 @@ cc = meson.get_compiler('c') deps = [ # dependency('glib-2.0', version: '>=2.26.0'), + dependency('dbus-1', version: '>=1.3'), dependency('gio-2.0', version: '>=2.26.0'), dependency('gtk+-3.0', version: '>=3.0'), dependency('libcroco-0.6'), diff --git a/src/popover.rs b/src/popover.rs index c9b60fb7..ec5e5b3f 100644 --- a/src/popover.rs +++ b/src/popover.rs @@ -110,14 +110,11 @@ pub fn show(window: EekGtkKeyboard, position: ::layout::c::Bounds) { .map(|(_kind, name)| name.as_str()) .collect(); - let translations = system_locale() - .map(|locale| - locale.tags_for("messages") - .next().unwrap() // guaranteed to exist - .as_ref() - .to_owned() - ) - .and_then(|lang| resources::get_layout_names(lang.as_str())); + let translations = resources::get_layout_names(system_locale() + .tags_for("messages") + .next().unwrap() // guaranteed to exist by locale_config + .as_ref() + ); // sorted collection of human and machine names let mut human_names: Vec<(&str, &str)> = match translations {