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

fix: set installer language and keyboard layout #1375

Merged
merged 19 commits into from
Jun 26, 2024
Merged
Show file tree
Hide file tree
Changes from 10 commits
Commits
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
10 changes: 10 additions & 0 deletions rust/agama-lib/src/proxies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -182,3 +182,13 @@ trait Issues {
#[dbus_proxy(property)]
fn all(&self) -> zbus::Result<Vec<(String, String, u32, u32)>>;
}

#[dbus_proxy(
interface = "org.opensuse.Agama1.Locale",
default_service = "org.opensuse.Agama.Manager1",
default_path = "/org/opensuse/Agama/Manager1"
)]
trait Locale {
/// SetLocale method
fn set_locale(&self, locale: &str) -> zbus::Result<()>;
}
3 changes: 1 addition & 2 deletions rust/agama-lib/src/software/proxies.rs
Original file line number Diff line number Diff line change
Expand Up @@ -80,8 +80,7 @@ trait SoftwareProduct {
/// SelectProduct method
fn select_product(&self, id: &str) -> zbus::Result<(u32, String)>;

/// AvailableProducts property
#[dbus_proxy(property)]
/// AvailableProducts method
fn available_products(&self) -> zbus::Result<Vec<Product>>;

/// SelectedProduct property
Expand Down
11 changes: 9 additions & 2 deletions rust/agama-server/src/l10n/web.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,9 @@ use crate::{
error::Error,
web::{Event, EventsSender},
};
use agama_lib::{error::ServiceError, localization::LocaleProxy};
use agama_lib::{
error::ServiceError, localization::LocaleProxy, proxies::LocaleProxy as ManagerLocaleProxy,
};
use agama_locale_data::LocaleId;
use axum::{
extract::State,
Expand All @@ -24,6 +26,7 @@ use tokio::sync::RwLock;
struct LocaleState<'a> {
locale: Arc<RwLock<L10n>>,
proxy: LocaleProxy<'a>,
manager_proxy: ManagerLocaleProxy<'a>,
events: EventsSender,
}

Expand All @@ -37,9 +40,11 @@ pub async fn l10n_service(
let id = LocaleId::default();
let locale = L10n::new_with_locale(&id).unwrap();
let proxy = LocaleProxy::new(&dbus).await?;
let manager_proxy = ManagerLocaleProxy::new(&dbus).await?;
let state = LocaleState {
locale: Arc::new(RwLock::new(locale)),
proxy,
manager_proxy,
events,
};

Expand Down Expand Up @@ -144,7 +149,9 @@ async fn set_config(
.try_into()
.map_err(|_e| LocaleError::UnknownLocale(ui_locale.to_string()))?;
data.translate(&locale)?;
changes.ui_locale = Some(locale.to_string());
let locale_string = locale.to_string();
state.manager_proxy.set_locale(&locale_string).await?;
changes.ui_locale = Some(locale_string);

_ = state.events.send(Event::LocaleChanged {
locale: locale.to_string(),
Expand Down
2 changes: 0 additions & 2 deletions rust/agama-server/src/network/model.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1314,7 +1314,6 @@ impl fmt::Display for InfinibandTransportMode {
}
}


#[derive(Default, Debug, PartialEq, Clone, Serialize)]
pub enum TunMode {
#[default]
Expand All @@ -1329,7 +1328,6 @@ pub struct TunConfig {
pub owner: Option<String>,
}


/// Represents a network change.
#[derive(Debug, Clone, Serialize)]
#[serde(rename_all = "camelCase")]
Expand Down
6 changes: 2 additions & 4 deletions rust/agama-server/src/network/nm/dbus.rs
Original file line number Diff line number Diff line change
Expand Up @@ -543,9 +543,8 @@ fn infiniband_config_from_dbus(conn: &OwnedNestedHash) -> Option<InfinibandConfi
}

fn tun_config_to_dbus(config: &TunConfig) -> HashMap<&str, zvariant::Value> {
let mut tun_config: HashMap<&str, zvariant::Value> = HashMap::from([
("mode", Value::new(config.mode.clone() as u32)),
]);
let mut tun_config: HashMap<&str, zvariant::Value> =
HashMap::from([("mode", Value::new(config.mode.clone() as u32))]);

if let Some(group) = &config.group {
tun_config.insert("group", group.into());
Expand All @@ -563,7 +562,6 @@ fn tun_config_from_dbus(conn: &OwnedNestedHash) -> Option<TunConfig> {

let mut tun_config = TunConfig::default();


if let Some(mode) = tun.get("mode") {
tun_config.mode = match mode.downcast_ref::<u32>()? {
2 => TunMode::Tap,
Expand Down
2 changes: 2 additions & 0 deletions service/lib/agama/dbus/clients/software.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

require "agama/dbus/clients/base"
require "agama/dbus/clients/with_issues"
require "agama/dbus/clients/with_locale"
require "agama/dbus/clients/with_progress"
require "agama/dbus/clients/with_service_status"

Expand All @@ -29,6 +30,7 @@ module DBus
module Clients
# D-Bus client for software configuration
class Software < Base
include WithLocale
include WithIssues
include WithProgress
include WithServiceStatus
Expand Down
2 changes: 2 additions & 0 deletions service/lib/agama/dbus/clients/storage.rb
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@

require "agama/dbus/clients/base"
require "agama/dbus/clients/with_service_status"
require "agama/dbus/clients/with_locale"
require "agama/dbus/clients/with_progress"
require "agama/dbus/clients/with_issues"

Expand All @@ -29,6 +30,7 @@ module DBus
module Clients
# D-Bus client for storage configuration
class Storage < Base
include WithLocale
include WithServiceStatus
include WithProgress
include WithIssues
Expand Down
42 changes: 42 additions & 0 deletions service/lib/agama/dbus/clients/with_locale.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# frozen_string_literal: true

# Copyright (c) [2024] 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.

module Agama
module DBus
module Clients
# Mixin for clients of services that define the Locale D-Bus interface
#
# Provides a method to interact with the API of the Locale interface.
#
# @note This mixin is expected to be included in a class inherited from {Clients::Base} and
# it requires a #dbus_object method that returns a {::DBus::Object} implementing the
# Locale interface.
module WithLocale
# Changes the service locale
#
# @param locale [String] new locale
def locale=(locale)
dbus_object.SetLocale(locale)
end
end
end
end
end
52 changes: 52 additions & 0 deletions service/lib/agama/dbus/interfaces/locale.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
# frozen_string_literal: true

# Copyright (c) [2024] 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"
require "dbus"

Yast.import "WFM"

module Agama
module DBus
module Interfaces
# Mixin to define the Locale interface.
#
# @note This mixin is expected to be included in a class that inherits from {DBus::BaseObject}
# and it requires a #locale= method that sets the service's locale.
module Locale
include Yast::I18n
include Yast::Logger

LOCALE_INTERFACE = "org.opensuse.Agama1.Locale"

def self.included(base)
base.class_eval do
dbus_interface LOCALE_INTERFACE do
dbus_method :SetLocale, "in locale:s" do |locale|
Copy link
Contributor

Choose a reason for hiding this comment

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

Names of locales differ, notably between Linux and browsers: en_US.UTF-8 vs en-us so we should specify what the API expects or we will get subtle bugs

Copy link
Contributor Author

Choose a reason for hiding this comment

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

In this case, it expects an en_US.UTF-8 kind of locale. That's the only locale that the backend understands. The transformation is performed in the installerL10n.jsx context.

I have added a comment to clarify that. Thanks!

self.locale = locale
end
end
end
end
end
end
end
end
8 changes: 8 additions & 0 deletions service/lib/agama/dbus/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
require "agama/dbus/base_object"
require "agama/dbus/with_service_status"
require "agama/dbus/interfaces/progress"
require "agama/dbus/interfaces/locale"
require "agama/dbus/interfaces/service_status"
require "agama/autoyast/converter"

Expand All @@ -34,6 +35,7 @@ class Manager < BaseObject
include WithServiceStatus
include Interfaces::Progress
include Interfaces::ServiceStatus
include Interfaces::Locale

PATH = "/org/opensuse/Agama/Manager1"
private_constant :PATH
Expand Down Expand Up @@ -141,6 +143,12 @@ def service_status
backend.service_status
end

def locale=(locale)
safe_run do
busy_while { backend.locale = locale }
end
end

private

# @return [Agama::Manager]
Expand Down
3 changes: 0 additions & 3 deletions service/lib/agama/dbus/manager_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,6 @@
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 @@ -74,8 +73,6 @@ def start
export
# We need locale for data from users
locale_client = Clients::Locale.instance
# TODO: test if we need to pass block with additional actions
@ui_locale = UILocale.new(locale_client)
manager.on_progress_change { dispatch } # make single thread more responsive
manager.startup_phase
end
Expand Down
8 changes: 8 additions & 0 deletions service/lib/agama/dbus/software/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@
require "agama/dbus/clients/locale"
require "agama/dbus/clients/network"
require "agama/dbus/interfaces/issues"
require "agama/dbus/interfaces/locale"
require "agama/dbus/interfaces/progress"
require "agama/dbus/interfaces/service_status"
require "agama/dbus/with_service_status"
Expand All @@ -37,6 +38,7 @@ class Manager < BaseObject
include Interfaces::Progress
include Interfaces::ServiceStatus
include Interfaces::Issues
include Interfaces::Locale

PATH = "/org/opensuse/Agama/Software1"
private_constant :PATH
Expand Down Expand Up @@ -134,6 +136,12 @@ def finish
busy_while { backend.finish }
end

def locale=(locale)
busy_while do
backend.locale = locale
end
end

private

# @return [Agama::Software]
Expand Down
10 changes: 9 additions & 1 deletion service/lib/agama/dbus/software/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
require "suse/connect"
require "agama/dbus/base_object"
require "agama/dbus/interfaces/issues"
require "agama/dbus/clients/locale"
require "agama/registration"

module Agama
Expand Down Expand Up @@ -90,7 +91,9 @@ def select_product(id)
private_constant :PRODUCT_INTERFACE

dbus_interface PRODUCT_INTERFACE do
dbus_reader :available_products, "a(ssa{sv})"
dbus_method :AvailableProducts, "out result:a(ssa{sv})" do
[available_products]
end

dbus_reader :selected_product, "s"

Expand Down Expand Up @@ -248,6 +251,11 @@ def registration_properties_changed
interfaces_and_properties[REGISTRATION_INTERFACE], [])
end

def product_properties_changed
dbus_properties_changed(PRODUCT_INTERFACE,
interfaces_and_properties[PRODUCT_INTERFACE], [])
end

# Result from calling to SUSE connect.
#
# @raise [Exception] if an unexpected error is found.
Expand Down
40 changes: 0 additions & 40 deletions service/lib/agama/dbus/software_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
require "agama/dbus/clients/locale"
require "agama/dbus/software"
require "agama/software"
require "agama/ui_locale"

require "yast"
Yast.import "Pkg"
Expand Down Expand Up @@ -58,10 +57,6 @@ def start
# for some reason the the "export" method must be called before
# registering the language change callback to work properly
export
@ui_locale = UILocale.new(Clients::Locale.instance) do |locale|
# call the language change handler
locale_handler(locale)
end
end

# Exports the software object through the D-Bus service
Expand Down Expand Up @@ -94,41 +89,6 @@ def dbus_objects
Agama::DBus::Software::Proposal.new(logger)
]
end

# Language change callback handler, activate new locale in the libzypp backend
# @param locale [String] the new locale
def locale_handler(locale)
language, = locale.split(".")

# set the locale in the Language module, when changing the repository
# (product) it calls Pkg.SetTextLocale(Language.language) internally
Yast::Language.Set(language)

# set libzypp locale (for communication only, Pkg.SetPackageLocale
# call can be used for *installing* the language packages)
Yast::Pkg.SetTextLocale(language)

# refresh all enabled repositories to download the missing translation files
Yast::Pkg.SourceGetCurrent(true).each do |src|
Yast::Pkg.SourceForceRefreshNow(src)
end

# remember the currently selected packages and patterns by YaST
# (ignore the automatic selections done by the solver)
#
# NOTE: we will need to handle also the tabooed and soft-locked objects
# when we allow to set them via UI or CLI
selected = Y2Packager::Resolvable.find(status: :selected, transact_by: :appl_high)

# save and reload all repositories to activate the new translations
Yast::Pkg.SourceSaveAll
Yast::Pkg.SourceFinishAll
Yast::Pkg.SourceRestore
Yast::Pkg.SourceLoad

# restore back the selected objects
selected.each { |s| Yast::Pkg.ResolvableInstall(s.name, s.kind) }
end
end
end
end
Loading
Loading