singleton-client-test 0.7.7.3 → 0.7.7.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/sgtn-client/api/source.rb +0 -3
- data/lib/sgtn-client/api/t.rb +2 -0
- data/lib/sgtn-client/api/translation.rb +42 -30
- data/lib/sgtn-client/common/data.rb +1 -1
- data/lib/sgtn-client/common/single_operation.rb +7 -8
- data/lib/sgtn-client/common.rb +10 -0
- data/lib/sgtn-client/core/cache.rb +13 -16
- data/lib/sgtn-client/core/config.rb +55 -174
- data/lib/sgtn-client/i18n_backend.rb +48 -0
- data/lib/sgtn-client/loader/cache.rb +24 -41
- data/lib/sgtn-client/loader/chain_loader.rb +3 -1
- data/lib/sgtn-client/loader/loader_factory.rb +6 -13
- data/lib/sgtn-client/loader/local_translation.rb +5 -10
- data/lib/sgtn-client/loader/server.rb +8 -13
- data/lib/sgtn-client/loader/single_loader.rb +22 -24
- data/lib/sgtn-client/loader/source.rb +6 -11
- data/lib/sgtn-client/loader/source_comparer.rb +1 -6
- data/lib/sgtn-client/loader.rb +19 -0
- data/lib/sgtn-client/sgtn-client.rb +44 -84
- data/lib/sgtn-client/util/cache-util.rb +6 -16
- data/lib/sgtn-client/util/locale-util.rb +59 -28
- data/lib/sgtn-client/util/string-util.rb +5 -2
- data/lib/sgtn-client/util/validate-util.rb +10 -20
- data/lib/singleton-client.rb +16 -6
- data/lib/singleton-ruby.rb +2 -3
- metadata +23 -41
- data/lib/sgtn-client/core/logging.rb +0 -52
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b1a0ab0b7bfa8a2fef42c229aae91032941499667f0885882f924d6a3f75694
|
4
|
+
data.tar.gz: be51ed5dbdf30cbc7f67353b5d96ba49e4e20a5de61ea9bd7d99d4f27785e1a9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d3a9b167165b5d6f6726ed8be0b07fadc7ef4aeb0c8ecb8f941bc77e5ff7ada988557f97098c33d1907fb7f24b1cac17f7df4fa3de3b96cce2e64a4240633c58
|
7
|
+
data.tar.gz: 44e84a38eb2e592793546c812817b751b0366b5af2ed0591eeaed1e4dd5b014af70b33674b7da69cac2873e16fb9ab3b47ff85d7d5f463b3a3bcfd987930ee7e
|
@@ -4,12 +4,9 @@
|
|
4
4
|
require 'sgtn-client/loader/source'
|
5
5
|
|
6
6
|
module SgtnClient
|
7
|
-
autoload :CacheUtil, 'sgtn-client/util/cache-util'
|
8
|
-
|
9
7
|
class Source
|
10
8
|
def self.loadBundles(locale)
|
11
9
|
SgtnClient.logger.debug "[Source][loadBundles]locale=#{locale}"
|
12
|
-
SgtnClient::Config.configurations.default = locale
|
13
10
|
end
|
14
11
|
end
|
15
12
|
end
|
data/lib/sgtn-client/api/t.rb
CHANGED
@@ -8,19 +8,19 @@ module SgtnClient
|
|
8
8
|
module Implementation
|
9
9
|
# <b>DEPRECATED:</b> Please use <tt>Sgtn:translate</tt> instead.
|
10
10
|
def getString(component, key, locale)
|
11
|
-
SgtnClient.logger.debug "[Translation.getString]component: #{component}, key: #{key}, locale: #{locale}"
|
11
|
+
SgtnClient.logger.debug { "[Translation.getString]component: #{component}, key: #{key}, locale: #{locale}" }
|
12
12
|
translate(key, component, locale) { nil }
|
13
13
|
end
|
14
14
|
|
15
15
|
# <b>DEPRECATED:</b> Please use <tt>Sgtn:translate</tt> instead.
|
16
16
|
def getString_p(component, key, plural_args, locale)
|
17
|
-
SgtnClient.logger.debug "[Translation][getString_p]component=#{component}, key=#{key}, locale=#{locale}"
|
17
|
+
SgtnClient.logger.debug { "[Translation][getString_p]component=#{component}, key=#{key}, locale=#{locale}" }
|
18
18
|
translate(key, component, locale, **plural_args) { nil }
|
19
19
|
end
|
20
20
|
|
21
21
|
# <b>DEPRECATED:</b> Please use <tt>Sgtn:translate</tt> instead.
|
22
22
|
def getString_f(component, key, args, locale, *_optionals)
|
23
|
-
SgtnClient.logger.debug "[Translation][getString_f]component=#{component}, key=#{key}, locale=#{locale}"
|
23
|
+
SgtnClient.logger.debug { "[Translation][getString_f]component=#{component}, key=#{key}, locale=#{locale}" }
|
24
24
|
s = translate(key, component, locale) { nil }
|
25
25
|
return nil if s.nil?
|
26
26
|
|
@@ -39,16 +39,16 @@ module SgtnClient
|
|
39
39
|
get_translations(component, locale)
|
40
40
|
end
|
41
41
|
|
42
|
-
# raise error when translation is not found
|
43
42
|
def translate(key, component, locale = nil, **kwargs)
|
44
|
-
SgtnClient.logger.debug "[#{method(__callee__).owner}.#{__callee__}] key: #{key}, component: #{component}, locale: #{locale}, args: #{kwargs}"
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
43
|
+
SgtnClient.logger.debug { "[#{method(__callee__).owner}.#{__callee__}] key: #{key}, component: #{component}, locale: #{locale}, args: #{kwargs}" }
|
44
|
+
|
45
|
+
begin
|
46
|
+
best_match_locale = LocaleUtil.get_best_locale(locale || self.locale, component)
|
47
|
+
messages, actual_locale = get_bundle_with_fallback(component, best_match_locale)
|
48
|
+
result = messages&.fetch(key, nil)
|
49
|
+
rescue StandardError => e
|
50
|
+
SgtnClient.logger.debug { "[#{method(__callee__).owner}.#{__callee__}] translation is missing. {#{key}, #{component}, #{locale}}. #{e}" }
|
51
|
+
result = nil
|
52
52
|
end
|
53
53
|
|
54
54
|
if result.nil?
|
@@ -61,31 +61,29 @@ module SgtnClient
|
|
61
61
|
if kwargs.empty?
|
62
62
|
result
|
63
63
|
else
|
64
|
-
|
65
|
-
result.localize(locale) % kwargs
|
64
|
+
result.localize(actual_locale) % kwargs
|
66
65
|
end
|
67
66
|
end
|
68
67
|
alias t translate
|
69
68
|
|
70
69
|
def get_translations(component, locale = nil)
|
71
|
-
SgtnClient.logger.debug "[#{method(__callee__).owner}.#{__callee__}] component: #{component}, locale: #{locale}"
|
70
|
+
SgtnClient.logger.debug { "[#{method(__callee__).owner}.#{__callee__}] component: #{component}, locale: #{locale}" }
|
72
71
|
|
73
|
-
|
74
|
-
|
75
|
-
if items.nil? && !LocaleUtil.is_source_locale(locale)
|
76
|
-
items = get_bundle(component, LocaleUtil.get_source_locale)
|
77
|
-
locale = LocaleUtil.get_source_locale
|
78
|
-
end
|
72
|
+
best_match_locale = LocaleUtil.get_best_locale(locale || self.locale, component)
|
73
|
+
messages, actual_locale = get_bundle_with_fallback(component, best_match_locale)
|
79
74
|
|
80
|
-
{ 'component' => component, 'locale' =>
|
75
|
+
{ 'component' => component, 'locale' => actual_locale, 'messages' => messages } if messages
|
76
|
+
rescue StandardError => e
|
77
|
+
SgtnClient.logger.error "[#{method(__callee__).owner}.#{__callee__}] translations are missing. {#{component}, #{locale}}. #{e}"
|
78
|
+
nil
|
81
79
|
end
|
82
80
|
|
83
81
|
def locale
|
84
|
-
RequestStore.store[:locale] ||=
|
82
|
+
RequestStore.store[:locale] ||= LocaleUtil.get_fallback_locale
|
85
83
|
end
|
86
84
|
|
87
85
|
def locale=(value)
|
88
|
-
RequestStore.store[:locale] =
|
86
|
+
RequestStore.store[:locale] = value
|
89
87
|
end
|
90
88
|
|
91
89
|
private
|
@@ -99,15 +97,29 @@ module SgtnClient
|
|
99
97
|
end
|
100
98
|
|
101
99
|
def get_bundle!(component, locale)
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
100
|
+
SgtnClient.config.loader.get_bundle(component, locale)
|
101
|
+
rescue StandardError
|
102
|
+
# delete the locale from the available_bundles of component to avoid repeated calls to server
|
103
|
+
SgtnClient.config.available_bundles.delete(Common::BundleID.new(component, locale))
|
104
|
+
SgtnClient.config.available_locales(component)&.delete(locale)
|
105
|
+
SgtnClient.config.changed
|
106
|
+
SgtnClient.config.notify_observers(:available_locales, component)
|
107
|
+
raise
|
108
|
+
end
|
109
|
+
|
110
|
+
def get_bundle_with_fallback(component, locale)
|
111
|
+
messages = get_bundle(component, locale)
|
112
|
+
return messages, locale if messages
|
113
|
+
|
114
|
+
LocaleUtil.locale_fallbacks.each do |l|
|
115
|
+
next if l == locale
|
107
116
|
|
108
|
-
|
117
|
+
messages = get_bundle(component, l)
|
118
|
+
return messages, l if messages
|
119
|
+
end
|
109
120
|
end
|
110
121
|
end
|
122
|
+
|
111
123
|
extend Implementation
|
112
124
|
end
|
113
125
|
end
|
@@ -3,25 +3,24 @@
|
|
3
3
|
|
4
4
|
module SgtnClient
|
5
5
|
class SingleOperation
|
6
|
-
def initialize(*conditions, &
|
7
|
-
raise 'no way to create a new obj' unless
|
6
|
+
def initialize(*conditions, &creator)
|
7
|
+
raise 'no way to create a new obj' unless creator
|
8
8
|
|
9
9
|
@lock = Mutex.new
|
10
10
|
@hash = {}
|
11
11
|
|
12
12
|
@conditions = conditions
|
13
|
-
@creator =
|
13
|
+
@creator = creator
|
14
14
|
end
|
15
15
|
|
16
|
-
# return new created object
|
17
|
-
def operate(id,
|
16
|
+
# return new created object (return nil possibly)
|
17
|
+
def operate(id, &block)
|
18
18
|
@lock.synchronize do
|
19
19
|
obj = @hash[id]
|
20
20
|
@conditions.each do |con|
|
21
|
-
return obj unless con.call(id, obj
|
21
|
+
return obj unless con.call(id, obj)
|
22
22
|
end
|
23
|
-
|
24
|
-
@hash[id] = @creator.call(id, obj, *args)
|
23
|
+
@hash[id] = @creator.call(id, &block)
|
25
24
|
end
|
26
25
|
end
|
27
26
|
|
@@ -1,34 +1,31 @@
|
|
1
1
|
# Copyright 2022 VMware, Inc.
|
2
2
|
# SPDX-License-Identifier: EPL-2.0
|
3
3
|
|
4
|
-
require '
|
4
|
+
require 'time'
|
5
5
|
|
6
6
|
module SgtnClient::Core
|
7
7
|
class Cache
|
8
8
|
Entry = Struct.new(:expiry, :items)
|
9
9
|
|
10
|
-
def self.initialize(disabled=false, opts={})
|
11
|
-
@@opts = opts
|
12
|
-
SgtnClient.logger.debug "[Cache][initialize] Disable cache? #{disabled}"
|
13
|
-
@@data = Hash.new
|
14
|
-
end
|
15
|
-
|
16
10
|
def self.get(key)
|
17
|
-
SgtnClient.logger.debug "[Cache][get]get cache for key: "
|
18
|
-
return
|
11
|
+
SgtnClient.logger.debug { "[Cache][get]get cache for key: #{key}" }
|
12
|
+
return data&.dig(key)
|
19
13
|
end
|
20
14
|
|
21
|
-
def self.put(key, items, ttl
|
22
|
-
ttl ||= @@opts[:ttl]
|
15
|
+
def self.put(key, items, ttl)
|
23
16
|
# hours from new
|
24
|
-
SgtnClient.logger.debug "[Cache][put]put cache for key '
|
25
|
-
|
17
|
+
SgtnClient.logger.debug { "[Cache][put]put cache for key '#{key}' with expired time at'" + (Time.now + ttl*60).to_s }
|
18
|
+
data[key] = Entry.new(Time.now + ttl*60, items)
|
26
19
|
end
|
27
20
|
|
28
21
|
def self.clear
|
29
|
-
SgtnClient.logger.debug "[Cache][clear]clear cache!"
|
30
|
-
|
22
|
+
SgtnClient.logger.debug { "[Cache][clear]clear cache!" }
|
23
|
+
@data = {}
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.data
|
27
|
+
@data ||= {}
|
31
28
|
end
|
32
29
|
end
|
33
30
|
|
34
|
-
end
|
31
|
+
end
|
@@ -1,205 +1,86 @@
|
|
1
1
|
# Copyright 2022 VMware, Inc.
|
2
2
|
# SPDX-License-Identifier: EPL-2.0
|
3
3
|
|
4
|
-
require '
|
5
|
-
require 'yaml'
|
4
|
+
require 'concurrent/map'
|
6
5
|
require 'observer'
|
6
|
+
require 'set'
|
7
|
+
require 'singleton'
|
7
8
|
|
8
9
|
module SgtnClient
|
9
|
-
#
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
10
|
+
class Config # :nodoc:
|
11
|
+
include Observable
|
12
|
+
include Singleton
|
13
|
+
|
14
|
+
attr_accessor :product_name, :version, :vip_server, :translation_bundle, :source_bundle, :cache_expiry_period, :log_file, :log_level
|
15
|
+
|
16
|
+
attr_writer :logger
|
17
|
+
|
18
|
+
def logger
|
19
|
+
@logger ||= if log_file
|
20
|
+
puts "create log file: '#{log_file}', level: #{log_level}"
|
21
|
+
require 'lumberjack'
|
22
|
+
Lumberjack::Logger.new(log_file, level: log_level, max_size: '1M', keep: 4)
|
23
|
+
else
|
24
|
+
require 'logger'
|
25
|
+
Logger.new(STDOUT, level: log_level || Logger::INFO)
|
26
|
+
end
|
27
|
+
end
|
14
28
|
|
15
|
-
|
29
|
+
def loader
|
30
|
+
@loader ||= TranslationLoader::LoaderFactory.create(self)
|
31
|
+
end
|
16
32
|
|
17
|
-
def
|
18
|
-
|
33
|
+
def available_bundles
|
34
|
+
loader.available_bundles
|
35
|
+
rescue StandardError => e
|
36
|
+
SgtnClient.logger.error 'failed to get available bundles'
|
37
|
+
SgtnClient.logger.error e
|
38
|
+
Set.new
|
19
39
|
end
|
20
40
|
|
21
|
-
def
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
begin
|
28
|
-
config.dup.merge!(env)
|
29
|
-
rescue Errno::ENOENT => error
|
30
|
-
Config.new(env)
|
31
|
-
end
|
32
|
-
else
|
33
|
-
Config.config(env, override_configurations)
|
34
|
-
end
|
41
|
+
def available_components
|
42
|
+
bundles = available_bundles
|
43
|
+
return Set.new if bundles.nil? || bundles.empty?
|
44
|
+
|
45
|
+
define_bundles_methods(bundles) unless bundles.respond_to?(:components)
|
46
|
+
bundles.components
|
35
47
|
end
|
36
48
|
|
37
|
-
|
49
|
+
def available_locales(component)
|
50
|
+
bundles = available_bundles
|
51
|
+
return Set.new if bundles.nil? || bundles.empty?
|
38
52
|
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
class Config
|
43
|
-
extend Observable
|
44
|
-
|
45
|
-
attr_accessor :username, :password, :signature, :app_id, :cert_path,
|
46
|
-
:token, :token_secret, :subject,
|
47
|
-
:http_timeout, :http_proxy,
|
48
|
-
:device_ipaddress, :sandbox_email_address,
|
49
|
-
:mode, :endpoint, :merchant_endpoint, :platform_endpoint, :ipn_endpoint,
|
50
|
-
:rest_endpoint, :rest_token_endpoint, :client_id, :client_secret,
|
51
|
-
:openid_endpoint, :openid_redirect_uri, :openid_client_id, :openid_client_secret,
|
52
|
-
:verbose_logging, :product_name, :version, :vip_server,
|
53
|
-
:translation_bundle, :source_bundle, :cache_expiry_period, :disable_cache, :default_language
|
54
|
-
|
55
|
-
|
56
|
-
# Create Config object
|
57
|
-
# === Options(Hash)
|
58
|
-
# * <tt>username</tt> -- Username
|
59
|
-
# * <tt>password</tt> -- Password
|
60
|
-
# * <tt>signature</tt> (Optional if certificate present) -- Signature
|
61
|
-
# * <tt>app_id</tt> -- Application ID
|
62
|
-
# * <tt>cert_path</tt> (Optional if signature present) -- Certificate file path
|
63
|
-
def initialize(options)
|
64
|
-
merge!(options)
|
53
|
+
define_bundles_methods(bundles) unless bundles.respond_to?(:locales)
|
54
|
+
bundles.locales(component)
|
65
55
|
end
|
66
56
|
|
67
|
-
|
68
|
-
def merge!(options)
|
57
|
+
def update(options)
|
69
58
|
options.each do |key, value|
|
70
59
|
send("#{key}=", value)
|
71
60
|
end
|
72
|
-
self
|
73
61
|
end
|
74
|
-
|
75
|
-
class << self
|
76
|
-
|
77
|
-
@@config_cache = {}
|
78
|
-
def load(file_name, default_env = default_environment)
|
79
|
-
@@config_cache = {}
|
80
|
-
@@configurations = read_configurations(file_name)
|
81
|
-
@@default_environment = default_env
|
82
|
-
config
|
83
|
-
end
|
84
62
|
|
63
|
+
private
|
85
64
|
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
end
|
90
|
-
|
65
|
+
def define_bundles_methods(bundles)
|
66
|
+
bundles.instance_eval do |_|
|
67
|
+
@component_locales ||= Concurrent::Map.new
|
91
68
|
|
92
|
-
|
93
|
-
|
94
|
-
@@default_environment = env.to_s
|
69
|
+
def components
|
70
|
+
@components ||= reduce(Set.new) { |components, id| components << id.component }
|
95
71
|
end
|
96
72
|
|
97
|
-
def
|
98
|
-
begin
|
99
|
-
|
100
|
-
rescue Errno::ENOENT
|
101
|
-
self.configurations = { default_environment => options }
|
102
|
-
end
|
103
|
-
block.call(self.config) if block
|
104
|
-
self.config
|
105
|
-
end
|
106
|
-
alias_method :set_config, :configure
|
107
|
-
|
108
|
-
# Create or Load Config object based on given environment and configurations.
|
109
|
-
# === Attributes
|
110
|
-
# * <tt>env</tt> (Optional) -- Environment name
|
111
|
-
# * <tt>override_configuration</tt> (Optional) -- Override the configuration given in file.
|
112
|
-
# === Example
|
113
|
-
# Config.config
|
114
|
-
# Config.config(:development)
|
115
|
-
# Config.config(:development, { :app_id => "XYZ" })
|
116
|
-
def config(env = default_environment, override_configuration = {})
|
117
|
-
if env.is_a? Hash
|
118
|
-
override_configuration = env
|
119
|
-
env = default_environment
|
120
|
-
end
|
121
|
-
if override_configuration.nil? or override_configuration.empty?
|
122
|
-
default_config(env)
|
123
|
-
else
|
124
|
-
default_config(env).dup.merge!(override_configuration)
|
125
|
-
end
|
126
|
-
end
|
127
|
-
|
128
|
-
def default_config(env = nil)
|
129
|
-
env = (env || default_environment).to_s
|
130
|
-
if configurations[env]
|
131
|
-
@@config_cache[env] ||= new(configurations[env])
|
132
|
-
else
|
133
|
-
raise SgtnClient::Exceptions::MissingConfig.new("Configuration[#{env}] NotFound")
|
134
|
-
end
|
135
|
-
end
|
136
|
-
|
137
|
-
# Get raw configurations in Hash format.
|
138
|
-
def configurations
|
139
|
-
@@configurations ||= read_configurations
|
140
|
-
end
|
141
|
-
|
142
|
-
# Set configuration
|
143
|
-
def configurations=(configs)
|
144
|
-
@@config_cache = {}
|
145
|
-
@@configurations = configs && Hash[configs.map{|k,v| [k.to_s, v] }]
|
146
|
-
end
|
73
|
+
def locales(component)
|
74
|
+
@component_locales[component] ||= begin
|
75
|
+
return Set.new unless components.include?(component)
|
147
76
|
|
148
|
-
|
149
|
-
def logger=(logger)
|
150
|
-
Logging.logger = logger
|
151
|
-
end
|
152
|
-
|
153
|
-
# Get logger
|
154
|
-
def logger
|
155
|
-
if @@configurations[:mode] == 'live' and Logging.logger.level == Logger::DEBUG
|
156
|
-
Logging.logger.warn "DEBUG log level not allowed in live mode for security of confidential information. Changing log level to INFO..."
|
157
|
-
Logging.logger.level = Logger::INFO
|
77
|
+
each_with_object(Set.new) { |id, locales| locales << id.locale if id.component == component }
|
158
78
|
end
|
159
|
-
Logging.logger
|
160
79
|
end
|
80
|
+
end
|
161
81
|
|
162
|
-
|
163
|
-
|
164
|
-
@loader ||= begin
|
165
|
-
config = SgtnClient::Config.configurations[SgtnClient::Config.default_environment]
|
166
|
-
SgtnClient::TranslationLoader::LoaderFactory.create(config)
|
167
|
-
end
|
168
|
-
end
|
169
|
-
|
170
|
-
def available_bundles
|
171
|
-
loader.available_bundles
|
172
|
-
rescue StandardError => e
|
173
|
-
SgtnClient.logger.error 'failed to get available bundles'
|
174
|
-
SgtnClient.logger.error e
|
175
|
-
Set.new
|
176
|
-
end
|
177
|
-
|
178
|
-
def available_locales
|
179
|
-
bundles = available_bundles
|
180
|
-
return Set.new if bundles.nil? || bundles.empty?
|
181
|
-
|
182
|
-
unless bundles.respond_to?(:locales)
|
183
|
-
def bundles.locales
|
184
|
-
@locales ||= reduce(Set.new) { |locales, id| locales << id.locale }
|
185
|
-
end
|
186
|
-
changed
|
187
|
-
notify_observers(:available_locales)
|
188
|
-
end
|
189
|
-
bundles.locales
|
190
|
-
end
|
191
|
-
|
192
|
-
private
|
193
|
-
# Read configurations from the given file name
|
194
|
-
# === Arguments
|
195
|
-
# * <tt>file_name</tt> (Optional) -- Configuration file path
|
196
|
-
def read_configurations(file_name = "config/sgtnclient.yml")
|
197
|
-
erb = ERB.new(File.read(file_name))
|
198
|
-
erb.filename = file_name
|
199
|
-
YAML.load(erb.result)
|
200
|
-
end
|
201
|
-
|
82
|
+
changed
|
83
|
+
notify_observers(:available_locales)
|
202
84
|
end
|
203
85
|
end
|
204
|
-
|
205
86
|
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
# Copyright 2022 VMware, Inc.
|
2
|
+
# SPDX-License-Identifier: EPL-2.0
|
3
|
+
|
4
|
+
require 'i18n'
|
5
|
+
|
6
|
+
module SgtnClient # :nodoc:
|
7
|
+
# When integrating Singleton in a client application that is already using [I18n::Backend (https://www.rubydoc.info/github/svenfuchs/i18n/master/I18n/Backend/), it would be useful to have Singleton override the said module in order to minimize necessary changes. Here is a common usage:
|
8
|
+
#
|
9
|
+
# I18n::Backend::Simple.include(I18n::Backend::Fallbacks) # add fallbacks behavior to current backend
|
10
|
+
# I18n.backend = I18n::Backend::Chain.new(Sgtn::I18nBackend.new(component_name), I18n.backend)
|
11
|
+
# I18n.enforce_available_locales=false # disable available locales check
|
12
|
+
# I18n.default_locale = :en
|
13
|
+
class I18nBackend
|
14
|
+
def initialize(component)
|
15
|
+
@component = component
|
16
|
+
end
|
17
|
+
|
18
|
+
def initialized?
|
19
|
+
@initialized ||= true
|
20
|
+
end
|
21
|
+
|
22
|
+
def load_translations(*) end
|
23
|
+
|
24
|
+
def store_translations(*) end
|
25
|
+
|
26
|
+
def available_locales
|
27
|
+
SgtnClient.config.available_locales(@component).to_a
|
28
|
+
end
|
29
|
+
|
30
|
+
def reload!; end
|
31
|
+
|
32
|
+
def eager_load!; end
|
33
|
+
|
34
|
+
def translations; end
|
35
|
+
|
36
|
+
def exists?(locale, key, options)
|
37
|
+
!!(translate(locale, key, options) { nil })
|
38
|
+
end
|
39
|
+
|
40
|
+
def translate(locale, key, options)
|
41
|
+
flat_key = I18n::Backend::Flatten.normalize_flat_keys(locale, key, options[:scope], '.')
|
42
|
+
values = options.except(*I18n::RESERVED_KEYS)
|
43
|
+
Translation.translate(flat_key, @component, locale, **values) { nil }
|
44
|
+
end
|
45
|
+
|
46
|
+
def localize(locale, object, format, options) end
|
47
|
+
end
|
48
|
+
end
|
@@ -4,66 +4,49 @@
|
|
4
4
|
# SPDX-License-Identifier: EPL-2.0
|
5
5
|
|
6
6
|
module SgtnClient
|
7
|
-
autoload :CacheUtil, 'sgtn-client/util/cache-util'
|
8
|
-
|
9
7
|
module TranslationLoader
|
10
|
-
autoload :CONSTS, 'sgtn-client/loader/consts'
|
11
|
-
|
12
8
|
module Cache # :nodoc:
|
13
9
|
# get from cache, return expired data immediately
|
14
10
|
def get_bundle(component, locale)
|
15
|
-
SgtnClient.logger.debug "[#{__FILE__}][#{__callee__}] component=#{component}, locale=#{locale}"
|
11
|
+
SgtnClient.logger.debug { "[#{__FILE__}][#{__callee__}] component=#{component}, locale=#{locale}" }
|
16
12
|
|
17
|
-
key =
|
18
|
-
cache_item =
|
13
|
+
key = Common::BundleID.new(component, locale)
|
14
|
+
cache_item = CacheUtil.get_cache(key)
|
19
15
|
if cache_item
|
20
|
-
if
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
rescue StandardError => e
|
25
|
-
SgtnClient.logger.error "an error occured while loading bundle: component=#{component}, locale=#{locale}"
|
26
|
-
SgtnClient.logger.error e
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
return cache_item.dig(:items)
|
16
|
+
load_bundle(component, locale, sync: false) if CacheUtil.is_expired(cache_item)
|
17
|
+
cache_item[:items]
|
18
|
+
else
|
19
|
+
load_bundle(component, locale)
|
31
20
|
end
|
21
|
+
end
|
32
22
|
|
33
|
-
|
23
|
+
def available_bundles
|
24
|
+
SgtnClient.logger.debug { "[#{__FILE__}][#{__callee__}]" }
|
25
|
+
|
26
|
+
cache_item = CacheUtil.get_cache(CONSTS::AVAILABLE_BUNDLES_KEY)
|
27
|
+
if cache_item
|
28
|
+
super(sync: false) if CacheUtil.is_expired(cache_item)
|
29
|
+
cache_item[:items]
|
30
|
+
else
|
31
|
+
super
|
32
|
+
end
|
34
33
|
end
|
34
|
+
end
|
35
35
|
|
36
|
-
|
36
|
+
module CacheFiller
|
37
37
|
def load_bundle(component, locale)
|
38
|
-
SgtnClient.logger.debug "[#{__FILE__}][#{__callee__}] component=#{component}, locale=#{locale}"
|
38
|
+
SgtnClient.logger.debug { "[#{__FILE__}][#{__callee__}] component=#{component}, locale=#{locale}" }
|
39
39
|
|
40
|
-
key = SgtnClient::CacheUtil.get_cachekey(component, locale)
|
41
40
|
item = super
|
42
|
-
|
41
|
+
CacheUtil.write_cache(Common::BundleID.new(component, locale), item) if item
|
43
42
|
item
|
44
43
|
end
|
45
44
|
|
46
45
|
def available_bundles
|
47
|
-
SgtnClient.logger.debug "[#{__FILE__}][#{__callee__}]"
|
48
|
-
|
49
|
-
cache_item = SgtnClient::CacheUtil.get_cache(CONSTS::AVAILABLE_BUNDLES_KEY)
|
50
|
-
if cache_item
|
51
|
-
if SgtnClient::CacheUtil.is_expired(cache_item)
|
52
|
-
Thread.new do # TODO: Use one thread
|
53
|
-
begin
|
54
|
-
item = super
|
55
|
-
SgtnClient::CacheUtil.write_cache(CONSTS::AVAILABLE_BUNDLES_KEY, item) if item
|
56
|
-
rescue StandardError => e
|
57
|
-
SgtnClient.logger.error 'an error occured while loading available bundles.'
|
58
|
-
SgtnClient.logger.error e
|
59
|
-
end
|
60
|
-
end
|
61
|
-
end
|
62
|
-
return cache_item.dig(:items)
|
63
|
-
end
|
46
|
+
SgtnClient.logger.debug { "[#{__FILE__}][#{__callee__}]" }
|
64
47
|
|
65
48
|
item = super
|
66
|
-
|
49
|
+
CacheUtil.write_cache(CONSTS::AVAILABLE_BUNDLES_KEY, item) if item # TODO: don't save when empty
|
67
50
|
item
|
68
51
|
end
|
69
52
|
end
|