I have the following complicated hash structure (among many) that looks like the following:
hash = {"en-us"=>
{:learn_more=>"Learn more",
:non_apple_desktop=>"To redeem, open this link.",
:value_prop_safety=>"",
:storage_size=>
{:apple_tv_1_month_tms=>
{:cta=>"Offer",
:details=>"Get a 1-month subscription!.",
:disclaimer=>"This offer expires on December 10, 2021.",
:header=>"Watch The Morning Show ",
:normal_price=>"$2.99"}
}
}
}
What I'd like to do is to have a function that will produce the following string output based off the hash structure:
en-us.storage_size.apple_tv_1_month_tms.cta: Offer
en-us.storage_size.apple_tv_1_month_tms.details: Get a 1-month subscription!.
en-us.storage_size.apple_tv_1_month_tms.disclaimer: This offer expires on December 10, 2021.
en-us.storage_size.apple_tv_1_month_tms.header: Watch The Morning Show
en-us.storage_size.apple_tv_1_month_tms.normal_price: $2.99
en-us.learn_more: Learn more
en-us.non_apple_desktop: To redeem, open this link.
en-us.value_prop_safety:
I've used this recursive function from another stackoverflow question that somewhat accomplishes this:
def show(hash, current_path = '')
string = ''
hash.each do |k,v|
if v.respond_to?(:each)
current_path += "#{k}."
show v, current_path
else
string += "#{current_path}#{k}: #{v}" + "\n"
end
end
string
end
If I place a puts
statement in the body of the method I can see the desired result but its line by line. What I need is to obtain the entirety of the output because I will be writing it to a csv. I can't seem to get it to work in its current incarnation.
If I were to place a puts show(hash)
into my irb, then I won't get any output. So in summary, I am trying to do the following:
show(hash) ----->
en-us.storage_size.apple_tv_1_month_tms.cta: Offer
en-us.storage_size.apple_tv_1_month_tms.details: Get a 1-month subscription!.
en-us.storage_size.apple_tv_1_month_tms.disclaimer: This offer expires on December 10, 2021.
en-us.storage_size.apple_tv_1_month_tms.header: Watch The Morning Show
en-us.storage_size.apple_tv_1_month_tms.normal_price: $2.99
en-us.learn_more: Learn more
en-us.non_apple_desktop: To redeem, open this link.
en-us.value_prop_safety:
This should be an easy recursive task but I can't pinpoint what exactly I've got wrong. Help would be greatly appreciated. Thank you.
In my opinion it is much more convenient to use i18n
gem
It has I18n::Backend::Flatten#flatten_translations
method. It receives a hash of translations (where the key is a locale and the value is another hash) and return a hash with all translations flattened, just as you need
Just convert the resulting hash to a string and you're done
require "i18n/backend/flatten"
include I18n::Backend::Flatten
locale_hash = {"en-us"=>
{:learn_more=>"Learn more",
:non_apple_desktop=>"To redeem, open this link.",
:value_prop_safety=>"",
:storage_size=>
{:apple_tv_1_month_tms=>
{:cta=>"Offer",
:details=>"Get a 1-month subscription!.",
:disclaimer=>"This offer expires on December 10, 2021.",
:header=>"Watch The Morning Show ",
:normal_price=>"$2.99"}
}
}
}
puts flatten_translations(nil, locale_hash, nil, nil).
map { |k, v| "#{k}: #{v}" }.
join("\n")
# will print
# en-us.learn_more: Learn more
# en-us.non_apple_desktop: To redeem, open this link.
# en-us.value_prop_safety:
# en-us.storage_size.apple_tv_1_month_tms.cta: Offer
# en-us.storage_size.apple_tv_1_month_tms.details: Get a 1-month subscription!.
# en-us.storage_size.apple_tv_1_month_tms.disclaimer: This offer expires on December 10, 2021.
# en-us.storage_size.apple_tv_1_month_tms.header: Watch The Morning Show
# en-us.storage_size.apple_tv_1_month_tms.normal_price: $2.99
Of course it's better to include not in main
object, but in some service object
require "i18n/backend/flatten"
class StringifyLocaleHash
include I18n::Backend::Flatten
attr_reader :locale_hash
def self.call(locale_hash)
new(locale_hash).call
end
def initialize(locale_hash)
@locale_hash = locale_hash
end
def call
flatten_translations(nil, locale_hash, nil, nil).
map { |k, v| "#{k}: #{v}" }.
join("\n")
end
end
# To get string call such way
StringifyLocaleHash.(locale_hash)