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 localized description feature #867

Merged
merged 1 commit into from
Nov 15, 2023
Merged
Show file tree
Hide file tree
Changes from all 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
25 changes: 0 additions & 25 deletions service/lib/agama/dbus/software/manager.rb
Original file line number Diff line number Diff line change
Expand Up @@ -149,31 +149,6 @@ def register_callbacks
backend.on_issues_change { issues_properties_changed }
end

# find translated product description if available
# @param data [Hash] product configuration from the YAML file
# @return [String,nil] Translated product description (if available)
# or the untranslated description, nil if not found
def localized_description(data)
translations = data["translations"]&.[]("description")
lang = ENV["LANG"] || ""

# no translations or language not set, return untranslated value
return data["description"] if !translations.is_a?(Hash) || lang.empty?

# remove the character encoding if present
lang = lang.split(".").first
# full matching (language + country)
return translations[lang] if translations[lang]

# remove the country part
lang = lang.split("_").first
# partial match (just the language)
return translations[lang] if translations[lang]

# fallback to original untranslated description
data["description"]
end

USER_SELECTED_PATTERN = 0
AUTO_SELECTED_PATTERN = 1
def compute_patterns
Expand Down
2 changes: 1 addition & 1 deletion service/lib/agama/dbus/software/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,7 @@ def issues

def available_products
backend.products.map do |product|
[product.id, product.display_name, { "description" => product.description }]
[product.id, product.display_name, { "description" => product.localized_description }]
end
end

Expand Down
49 changes: 45 additions & 4 deletions service/lib/agama/software/product.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,22 @@ class Product

# Name of the product to be display.
#
# @return [String]
# @return [String, nil]
attr_accessor :display_name

# Description of the product.
#
# @return [String]
# @return [String, nil]
attr_accessor :description

# Internal name of the product. This is relevant for registering the product.
#
# @return [String]
# @return [String, nil]
attr_accessor :name

# Version of the product. This is relevant for registering the product.
#
# @return [String] E.g., "1.0".
# @return [String, nil] E.g., "1.0".
attr_accessor :version

# List of repositories.
Expand Down Expand Up @@ -73,6 +73,19 @@ class Product
# @return [Array<String>]
attr_accessor :optional_patterns

# Product translations.
#
# @example
# product.translations #=>
# {
# "description" => {
# "cs" => "Czech translation",
# "es" => "Spanish translation"
# }
#
# @return [Hash<String, Hash<String, String>>]
attr_accessor :translations

# @param id [string] Product id.
def initialize(id)
@id = id
Expand All @@ -81,6 +94,34 @@ def initialize(id)
@optional_packages = []
@mandatory_patterns = []
@optional_patterns = []
@translations = {}
end

# Localized product description.
#
# If there is no translation for the current language, then the untranslated description is
# used.
#
# @return [String, nil]
def localized_description
translations = self.translations["description"]
lang = ENV["LANG"]

# No translations or language not set, return untranslated value.
return description unless translations && lang

# Remove the character encoding if present.
lang = lang.split(".").first
# Full matching (language + country)
return translations[lang] if translations[lang]

# Remove the country part.
lang = lang.split("_").first
# Partial match (just the language).
return translations[lang] if translations[lang]

# Fallback to original untranslated description.
description
end
end
end
Expand Down
1 change: 1 addition & 0 deletions service/lib/agama/software/product_builder.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@ def build
product.optional_packages = data[:optional_packages]
product.mandatory_patterns = data[:mandatory_patterns]
product.optional_patterns = data[:optional_patterns]
product.translations = attrs["translations"] || {}
end
end
end
Expand Down
64 changes: 0 additions & 64 deletions service/test/agama/dbus/software/manager_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -135,68 +135,4 @@
expect(installed).to eq(true)
end
end

describe "#available_base_products" do
# testing product with translations
products = {
"Tumbleweed" => {
"name" => "openSUSE Tumbleweed",
"description" => "Original description",
"translations" => {
"description" => {
"cs" => "Czech translation",
"es" => "Spanish translation"
}
}
}
}

it "returns product ID and name" do
expect(backend).to receive(:products).and_return(products)

product = subject.available_base_products.first
expect(product[0]).to eq("Tumbleweed")
expect(product[1]).to eq("openSUSE Tumbleweed")
end

it "returns untranslated description when the language is not set" do
allow(ENV).to receive(:[]).with("LANG").and_return(nil)
expect(backend).to receive(:products).and_return(products)

product = subject.available_base_products.first
expect(product[2]["description"]).to eq("Original description")
end

it "returns Czech translation if locale is \"cs_CZ.UTF-8\"" do
allow(ENV).to receive(:[]).with("LANG").and_return("cs_CZ.UTF-8")
expect(backend).to receive(:products).and_return(products)

product = subject.available_base_products.first
expect(product[2]["description"]).to eq("Czech translation")
end

it "returns Czech translation if locale is \"cs\"" do
allow(ENV).to receive(:[]).with("LANG").and_return("cs")
expect(backend).to receive(:products).and_return(products)

product = subject.available_base_products.first
expect(product[2]["description"]).to eq("Czech translation")
end

it "return untranslated description when translation is not available" do
allow(ENV).to receive(:[]).with("LANG").and_return("cs_CZ.UTF-8")

# testing product without translations
untranslated = {
"Tumbleweed" => {
"name" => "openSUSE Tumbleweed",
"description" => "Original description"
}
}
expect(backend).to receive(:products).and_return(untranslated)

product = subject.available_base_products.first
expect(product[2]["description"]).to eq("Original description")
end
end
end
40 changes: 27 additions & 13 deletions service/test/agama/software/product_builder_test.rb
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# frozen_string_literal: true

# Copyright (c) [2022-2023] SUSE LLC
# Copyright (c) [2023] SUSE LLC
#
# All Rights Reserved.
#
Expand Down Expand Up @@ -38,10 +38,16 @@
let(:products) do
[
{
"id" => "Test1",
"name" => "Product Test 1",
"description" => "This is a test product named Test 1",
"software" => {
"id" => "Test1",
"name" => "Product Test 1",
"description" => "This is a test product named Test 1",
"translations" => {
"description" => {
"cs" => "Czech",
"es" => "Spanish"
}
},
"software" => {
"installation_repositories" => [
{
"url" => "https://repos/test1/x86_64/product/",
Expand Down Expand Up @@ -141,7 +147,8 @@
mandatory_patterns: ["pattern1-1", "pattern1-2"],
optional_patterns: ["pattern1-3"],
mandatory_packages: ["package1-1", "package1-2", "package1-3"],
optional_packages: ["package1-5"]
optional_packages: ["package1-5"],
translations: { "description" => { "cs" => "Czech", "es" => "Spanish" } }
),
an_object_having_attributes(
id: "Test2",
Expand All @@ -153,7 +160,8 @@
mandatory_patterns: ["pattern2-1"],
optional_patterns: [],
mandatory_packages: [],
optional_packages: []
optional_packages: [],
translations: {}
)
)
end
Expand Down Expand Up @@ -183,7 +191,8 @@
mandatory_patterns: ["pattern1-1", "pattern1-2"],
optional_patterns: ["pattern1-4"],
mandatory_packages: ["package1-1", "package1-2", "package1-3"],
optional_packages: ["package1-5"]
optional_packages: ["package1-5"],
translations: { "description" => { "cs" => "Czech", "es" => "Spanish" } }
),
an_object_having_attributes(
id: "Test2",
Expand All @@ -195,7 +204,8 @@
mandatory_patterns: ["pattern2-1"],
optional_patterns: [],
mandatory_packages: [],
optional_packages: []
optional_packages: [],
translations: {}
),
an_object_having_attributes(
id: "Test3",
Expand All @@ -207,7 +217,8 @@
mandatory_patterns: [],
optional_patterns: ["pattern3-1"],
mandatory_packages: [],
optional_packages: []
optional_packages: [],
translations: {}
)
)
end
Expand Down Expand Up @@ -237,7 +248,8 @@
mandatory_patterns: ["pattern1-1", "pattern1-2"],
optional_patterns: [],
mandatory_packages: ["package1-1", "package1-2", "package1-4"],
optional_packages: ["package1-5"]
optional_packages: ["package1-5"],
translations: { "description" => { "cs" => "Czech", "es" => "Spanish" } }
),
an_object_having_attributes(
id: "Test3",
Expand All @@ -249,7 +261,8 @@
mandatory_patterns: [],
optional_patterns: [],
mandatory_packages: [],
optional_packages: []
optional_packages: [],
translations: {}
)
)
end
Expand Down Expand Up @@ -279,7 +292,8 @@
mandatory_patterns: ["pattern1-1", "pattern1-2"],
optional_patterns: [],
mandatory_packages: ["package1-1", "package1-2"],
optional_packages: ["package1-5"]
optional_packages: ["package1-5"],
translations: { "description" => { "cs" => "Czech", "es" => "Spanish" } }
)
)
end
Expand Down
64 changes: 64 additions & 0 deletions service/test/agama/software/product_test.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
# frozen_string_literal: true

# Copyright (c) [2023] 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_relative "../../test_helper"
require "agama/software/product"

describe Agama::Software::Product do
subject { described_class.new("Test") }

describe "#localized_description" do
before do
subject.description = "Original description"
subject.translations = {
"description" => {
"cs" => "Czech translation",
"es" => "Spanish translation"
}
}
end

it "returns untranslated description when the language is not set" do
allow(ENV).to receive(:[]).with("LANG").and_return(nil)

expect(subject.localized_description).to eq("Original description")
end

it "returns Czech translation if locale is \"cs_CZ.UTF-8\"" do
allow(ENV).to receive(:[]).with("LANG").and_return("cs_CZ.UTF-8")

expect(subject.localized_description).to eq("Czech translation")
end

it "returns Czech translation if locale is \"cs\"" do
allow(ENV).to receive(:[]).with("LANG").and_return("cs")

expect(subject.localized_description).to eq("Czech translation")
end

it "return untranslated description when translation is not available" do
allow(ENV).to receive(:[]).with("LANG").and_return("cs_CZ.UTF-8")
subject.translations = {}

expect(subject.localized_description).to eq("Original description")
end
end
end