Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

UI locale dbus #725

Merged
merged 21 commits into from
Aug 30, 2023
Merged
Show file tree
Hide file tree
Changes from 13 commits
Commits
Show all changes
21 commits
Select commit Hold shift + click to select a range
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
40 changes: 38 additions & 2 deletions rust/agama-dbus-server/src/locale.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
use crate::error::Error;
use agama_lib::connection_to;
use anyhow::Context;
use std::process::Command;
use std::{process::Command, fs::read_dir};
use zbus::{dbus_interface, Connection};

pub struct Locale {
locales: Vec<String>,
keymap: String,
timezone_id: String,
supported_locales: Vec<String>,
ui_locale: String,
}

#[dbus_interface(name = "org.opensuse.Agama.Locale1")]
Expand Down Expand Up @@ -89,6 +90,40 @@ impl Locale {
Ok(())
}


#[dbus_interface(property, name="UILocale")]
fn ui_locale(&self) -> &str {
&self.ui_locale
}

#[dbus_interface(property, name="UILocale")]
fn set_ui_locale(&mut self, locale: &str) {
self.ui_locale = locale.to_string();
}

/// Gets list of locales available on system.
///
/// # Examples
///
/// ```
/// use agama_dbus_server::locale::Locale;
/// let locale = Locale::new();
/// assert!(locale.list_ui_locales().unwrap().len() > 0);
/// ```
#[dbus_interface(name = "ListUILocales")]
pub fn list_ui_locales(&self) -> Result<Vec<String>, Error> {
// english is always available ui localization
let mut result = vec!["en".to_string()];
const DIR : &str = "/usr/share/YaST2/locale/";
let entries = read_dir(DIR).context("Reading YaST2 locale")?;
for entry in entries {
let entry = entry.context("Failed to read entry in YaST2 locale dir")?;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So we are returning an error if we cannot read any of the dirs, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

yeah, any read failure result in error. I would not expect it unless there is some issue with fs.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The /usr/share/YaST2/locale/ directory is owned by the base yast2 package so the error should not happen normally.

result.push(entry.file_name().to_str().context("Non UTF entry found in YaST2 locale dir")?.to_string());
jreidinger marked this conversation as resolved.
Show resolved Hide resolved
}

Ok(result)
}

/* support only keymaps for console for now
fn list_x11_keyboards(&self) -> Result<Vec<(String, String)>, Error> {
let keyboards = agama_locale_data::get_xkeyboards()?;
Expand Down Expand Up @@ -176,12 +211,13 @@ impl Locale {
}

impl Locale {
fn new() -> Self {
pub fn new() -> Self {
Self {
locales: vec!["en_US.UTF-8".to_string()],
keymap: "us".to_string(),
timezone_id: "America/Los_Angeles".to_string(),
supported_locales: vec!["en_US.UTF-8".to_string()],
ui_locale: "en".to_string()
}
}
}
Expand Down
29 changes: 28 additions & 1 deletion service/lib/agama/dbus/clients/locale.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@ module DBus
module Clients
# D-Bus client for locale configuration
class Locale < Base
INTERFACE_NAME = "org.opensuse.Agama.Locale1"

def initialize
super

Expand All @@ -44,6 +46,18 @@ def supported_locales=(locales)
dbus_object.supported_locales = locales
end

def ui_locale
dbus_object[INTERFACE_NAME]["UILocale"]
end

def ui_locale=(locale)
dbus_object[INTERFACE_NAME]["UILocale"] = locale
end

def available_ui_locales
dbus_object.ListUILocales
end

# Finishes the language installation
def finish
dbus_object.Commit
Expand All @@ -58,7 +72,20 @@ def finish
def on_language_selected(&block)
on_properties_change(dbus_object) do |_, changes, _|
languages = changes["Locales"]
block.call(languages)
block.call(languages) if languages
end
end

# Registers a callback to run when the ui locale changes
#
# @note Signal subscription is done only once. Otherwise, the latest subscription overrides
# the previous one.
#
# @param block [Proc] Callback to run when an ui locale changes
def on_ui_locale_change(&block)
on_properties_change(dbus_object) do |_, changes, _|
locale = changes["UILocale"]
block.call(locale) if locale
end
end

Expand Down
93 changes: 0 additions & 93 deletions service/lib/agama/dbus/language_service.rb

This file was deleted.

6 changes: 6 additions & 0 deletions service/lib/agama/dbus/manager_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,11 @@
require "agama/users"
require "agama/cockpit_manager"
require "agama/dbus/bus"
require "agama/dbus/clients/locale"
require "agama/dbus/manager"
require "agama/dbus/users"
require "agama/dbus/storage/proposal"
require "agama/ui_locale"

module Agama
module DBus
Expand Down Expand Up @@ -76,6 +78,10 @@ def initialize(config, logger = nil)
# @note The service runs its startup phase
def start
setup_cockpit
# We need locale for data from users
locale_client = Clients::Locale.new
# TODO: test if we need to pass block with additional actions
@ui_locale = UILocale.new(locale_client)
export
manager.on_progress_change { dispatch } # make single thread more responsive
manager.startup_phase
Expand Down
10 changes: 10 additions & 0 deletions service/lib/agama/dbus/software_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@

require "dbus"
require "agama/dbus/bus"
require "agama/dbus/clients/locale"
require "agama/dbus/software"
require "agama/software"
require "agama/ui_locale"

module Agama
module DBus
Expand All @@ -48,6 +50,14 @@ def initialize(config, logger = nil)
@backend.on_progress_change { dispatch }
end

# Starts software service. It does more then just #export method.
def start
locale_client = Clients::Locale.new
# TODO: test if we need to pass block with additional actions
@ui_locale = UILocale.new(locale_client)
export
end

# Exports the software object through the D-Bus service
def export
dbus_objects.each { |o| service.export(o) }
Expand Down
10 changes: 10 additions & 0 deletions service/lib/agama/dbus/storage_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,10 @@

require "dbus"
require "agama/dbus/bus"
require "agama/dbus/clients/locale"
require "agama/dbus/storage"
require "agama/storage"
require "agama/ui_locale"

module Agama
module DBus
Expand All @@ -48,6 +50,14 @@ def bus
Bus.current
end

# Starts storage service. It does more then just #export method.
def start
locale_client = Clients::Locale.new
# TODO: test if we need to pass block with additional actions
@ui_locale = UILocale.new(locale_client)
export
end

# Exports the storage proposal object through the D-Bus service
def export
dbus_objects.each { |o| service.export(o) }
Expand Down
57 changes: 57 additions & 0 deletions service/lib/agama/ui_locale.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# frozen_string_literal: true

# Copyright (c) [2022] SUSE LLC
#
# All Rights Reserved.
#
# This program is free software; you can redistribute it and/or modify it
# under the terms of version 2 of the GNU General Public License as published
# by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
# more details.
#
# You should have received a copy of the GNU General Public License along
# with this program; if not, contact SUSE LLC.
#
# To contact SUSE LLC about this file by physical or electronic mail, you may
# find current contact information at www.suse.com.

require "yast"

Yast.import "WFM"

module Agama
# Object responsible for managing changes of localization produced by dbus backend.
jreidinger marked this conversation as resolved.
Show resolved Hide resolved
class UILocale
include Yast::I18n
include Yast::Logger
# creates new UILocale object that will handle change of UI locale.
#
# @param [Agama::DBus::Clients::Locale] locale_client to communicate with dbus service
# @yield block is callback that is called when ui locale is changed
# to allow user to call methods that needs retranslation
def initialize(locale_client, &block)
@client = locale_client
change_locale(@client.ui_locale)
@client.on_ui_locale_change do |locale|
change_locale(locale)
block.call(locale) if block_given?
end
end

private

def change_locale(locale)
# TODO: check if we can use UTF-8 everywhere including strange arch consoles
Yast::WFM.SetLanguage(locale, "UTF-8")
# explicitelly set ENV to get localization also from libraries like libstorage
ENV["LANG"] = locale + ".UTF-8"
log.info "set yast language to #{locale}"
# explicit call to textdomain to force fast gettext change of language ASAP
textdomain "installation"
end
end
end
Loading