singleton-client-test 0.7.0.30 → 0.7.0.33

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 8bbeb4b91e49f392f67d86832ba947550035c57e5d95ed8a9ba3f7018bea1933
4
- data.tar.gz: 2f42e96d26b18919eca9dde3673b9b9ae20af3f627bf06fd21ebac63ce496e55
3
+ metadata.gz: a2a32a268d9bc9b395baeb2d296049cbbb29a40c081968d6e8a5ae364c39444c
4
+ data.tar.gz: fdf427aaf792fbff1bf6afa404d6e0aeeea030b9fa90b7eab578cbe46659656e
5
5
  SHA512:
6
- metadata.gz: 19ea390e3e040215ea4dd38d38ae4e36452c217a2e82e22bf638ac08798dda63797be2b346fd3bde89a9c6e5ff5aa415c02a21b0094518a3b698ebb3864ff383
7
- data.tar.gz: dfc215e21a95bf65a7b25799e13f80fc026fdc13e5b0566ab478a4977c5f73041c6754fc88ba8bef48ee2c0e26ee3721c887032614bd350ba125397f489fe35f
6
+ metadata.gz: 1ecfa3b8fbc1ef494e41a517a102856f4717d408845eeac43cd751c24df2a590404082cd00670b280fd8c404b3dd95ecd2ae5c06f7b0c0b23172b9eb7ab2fff7
7
+ data.tar.gz: 0a8aee2dd03eaa02c981cdfaa097ffbddebc2118c7c7a63625ad19ca332ecf582fac19a812339ef9920dac37765a03b30d9800d69cfe9dd2b854762ee0796170
@@ -1,71 +1,24 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
4
+ require 'sgtn-client/loader/local_source_bundle'
1
5
 
2
6
  module SgtnClient
3
-
4
- autoload :CacheUtil, "sgtn-client/util/cache-util"
7
+ autoload :CacheUtil, 'sgtn-client/util/cache-util'
5
8
 
6
9
  class Source
7
-
8
- def self.getSource(component, key, locale)
9
- SgtnClient.logger.debug "[Source][getSource]component=#{component}, key=#{key}, locale=#{locale}"
10
- cache_key = SgtnClient::CacheUtil.get_cachekey(component, locale)
11
- expired, items = SgtnClient::CacheUtil.get_cache(cache_key)
12
- if items.nil?
13
- items = getBundle(component, locale)
14
- SgtnClient::CacheUtil.write_cache(cache_key, items)
15
- else
16
- SgtnClient.logger.debug "[Source][getSource]getting sources from cache with key: " + cache_key
17
- end
18
- s = items.nil?? nil : items[locale][key]
19
- if items.nil? || s.nil?
20
- SgtnClient.logger.debug "[Source][getSource]source not found, return key: " + key
21
- #return key
22
- return nil
23
- else
24
- return s
25
- end
26
- end
27
-
28
- def self.getSources(component, locale)
29
- SgtnClient.logger.debug "[Source][getSources]component=#{component}, locale=#{locale}"
30
- cache_key = SgtnClient::CacheUtil.get_cachekey(component, locale)
31
- expired, items = SgtnClient::CacheUtil.get_cache(cache_key)
32
- if items.nil? || expired
33
- items = getBundle(component, locale)
34
- SgtnClient::CacheUtil.write_cache(cache_key, items)
35
- else
36
- SgtnClient.logger.debug "[Source][getSources]getting sources from cache with key: " + cache_key
37
- end
38
- return items
39
- end
40
-
41
- def self.loadBundles(locale)
42
- SgtnClient.logger.debug "[Source][loadBundles]locale=#{locale}"
43
- env = SgtnClient::Config.default_environment
44
- SgtnClient::Config.configurations.default = locale
45
- source_bundle = SgtnClient::Config.configurations[env]["source_bundle"]
46
- Dir.foreach(source_bundle) do |component|
47
- next if component == '.' || component == '..'
48
- yamlfile = File.join(source_bundle, component + "/" + locale + ".yml")
49
- bundle = SgtnClient::FileUtil.read_yml(yamlfile)
50
- cachekey = SgtnClient::CacheUtil.get_cachekey(component, locale)
51
- SgtnClient::CacheUtil.write_cache(cachekey,bundle)
52
- end
53
- end
54
-
55
- private
56
- def self.getBundle(component, locale)
57
- SgtnClient.logger.debug "[Source][getBundle]component=#{component}, locale=#{locale}"
58
- env = SgtnClient::Config.default_environment
59
- source_bundle = SgtnClient::Config.configurations[env]["source_bundle"]
60
- bundlepath = source_bundle + "/" + component + "/" + locale + ".yml"
61
- begin
62
- bundle = SgtnClient::FileUtil.read_yml(bundlepath)
63
- rescue => exception
64
- SgtnClient.logger.error exception.message
65
- end
66
- return bundle
10
+ def self.loadBundles(locale)
11
+ SgtnClient.logger.debug "[Source][loadBundles]locale=#{locale}"
12
+ env = SgtnClient::Config.default_environment
13
+ SgtnClient::Config.configurations.default = locale
14
+ source_bundle = SgtnClient::Config.configurations[env]['source_bundle']
15
+ Dir.foreach(source_bundle) do |component|
16
+ next if %w[. ..].include? component
17
+
18
+ bundle = load_bundle(component)
19
+ cachekey = SgtnClient::CacheUtil.get_cachekey(component, LocaleUtil.get_source_locale)
20
+ SgtnClient::CacheUtil.write_cache(cachekey, bundle)
67
21
  end
68
-
22
+ end
69
23
  end
70
-
71
- end
24
+ end
@@ -1,22 +1,24 @@
1
- module SgtnClient
2
- class T < Translation
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
3
 
4
- def self.s(key)
5
- locale = RequestStore.store[:locale]
6
- component = RequestStore.store[:component]
7
- return getString(component, key, locale)
8
- end
4
+ module SgtnClient
5
+ class T
6
+ def self.s(key)
7
+ locale = RequestStore.store[:locale]
8
+ component = RequestStore.store[:component]
9
+ Translation.getString(component, key, locale)
10
+ end
9
11
 
10
- def self.s_f(key, args)
11
- locale = RequestStore.store[:locale]
12
- component = RequestStore.store[:component]
13
- return getString_f(component, key, args, locale)
14
- end
12
+ def self.s_f(key, args)
13
+ locale = RequestStore.store[:locale]
14
+ component = RequestStore.store[:component]
15
+ Translation.getString_f(component, key, args, locale)
16
+ end
15
17
 
16
- def self.c()
17
- locale = RequestStore.store[:locale]
18
- component = RequestStore.store[:component]
19
- return getStrings(component, locale)
20
- end
18
+ def self.c
19
+ locale = RequestStore.store[:locale]
20
+ component = RequestStore.store[:component]
21
+ Translation.getStrings(component, locale)
21
22
  end
22
- end
23
+ end
24
+ end
@@ -1,147 +1,110 @@
1
- require 'multi_json'
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
2
3
 
3
4
  module SgtnClient
4
-
5
- module Core
6
- autoload :Request, "sgtn-client/core/request"
7
- autoload :Cache, "sgtn-client/core/cache"
8
- autoload :CacheUtil, "sgtn-client/util/cache-util"
9
- autoload :LocaleUtil, "sgtn-client/util/locale-util"
5
+ autoload :StringUtil, 'sgtn-client/util/string-util'
6
+
7
+ module TranslationLoader
8
+ autoload :LocalBundle, 'sgtn-client/loader/local_bundle'
9
+ autoload :ServerBundle, 'sgtn-client/loader/server_bundle'
10
+ autoload :SourceComparer, 'sgtn-client/loader/source_comparer'
11
+ autoload :SingleLoader, 'sgtn-client/loader/single_loader'
12
+ autoload :Cache, 'sgtn-client/loader/cache'
10
13
  end
11
-
12
- class Translation
13
-
14
- def self.getString(component, key, locale)
15
- SgtnClient.logger.debug "[Translation.getString]component: #{component}, key: #{key}, locale: #{locale}"
16
- str = getTranslation(component, key, locale)
17
- if str.nil?
18
- str = SgtnClient::Source.getSource(component, key, SgtnClient::Config.configurations.default)
19
- if str.nil?
20
- SgtnClient.logger.debug "[Translation][getString] Missing source string with key: #{key}, component: #{component}, locale: #{locale}"
21
- end
14
+
15
+ module Translation
16
+ def self.getString(component, key, locale)
17
+ SgtnClient.logger.debug "[Translation.getString]component: #{component}, key: #{key}, locale: #{locale}"
18
+ str = getTranslation(component, key, locale)
19
+ if str.nil? && !LocaleUtil.is_source_locale(locale)
20
+ str = getTranslation(component, key, LocaleUtil.get_source_locale)
21
+ end
22
+ str
23
+ end
24
+
25
+ def self.getString_p(component, key, plural_args, locale)
26
+ SgtnClient.logger.debug "[Translation][getString_p]component=#{component}, key=#{key}, locale=#{locale}"
27
+ str = getTranslation(component, key, locale)
28
+ if str.nil?
29
+ unless LocaleUtil.is_source_locale(locale)
30
+ str = getTranslation(component, key, LocaleUtil.get_source_locale)
31
+ str.to_plural_s(LocaleUtil.get_source_locale, plural_args) if str
22
32
  end
23
- str
33
+ else
34
+ locale = str.locale if str.is_a?(SgtnClient::StringUtil)
35
+ str.to_plural_s(locale, plural_args)
24
36
  end
37
+ end
25
38
 
26
- def self.getString_p(component, key, plural_args, locale)
27
- SgtnClient.logger.debug "[Translation][getString_p]component=#{component}, key=#{key}, locale=#{locale}"
28
- str = getTranslation(component, key, locale)
29
- if str.nil?
30
- str = SgtnClient::Source.getSource(component, key, SgtnClient::Config.configurations.default)
31
- if str.nil?
32
- SgtnClient.logger.debug "[Translation][getString_p] Missing source string with key: #{key}, component: #{component}, locale: #{locale}"
33
- return nil
34
- end
35
- str.to_plural_s(:en, plural_args)
36
- else
37
- str.to_plural_s(locale, plural_args)
39
+ def self.getString_f(component, key, args, locale, *optionals)
40
+ SgtnClient.logger.debug "[Translation][getString_f]component=#{component}, key=#{key}, locale=#{locale}"
41
+ s = getString(component, key, locale, *optionals)
42
+ return nil if s.nil?
43
+
44
+ if args.is_a?(Hash)
45
+ args.each do |source, arg|
46
+ s.gsub! "{#{source}}", arg
38
47
  end
48
+ elsif args.is_a?(Array)
49
+ s = s % args
39
50
  end
40
-
41
- def self.getString_f(component, key, args, locale, *optionals)
42
- SgtnClient.logger.debug "[Translation][getString_f]component=#{component}, key=#{key}, locale=#{locale}"
43
- s = getString(component, key, locale, *optionals)
44
- if s.nil?
45
- return nil
46
- end
47
- if args.is_a?(Hash)
48
- args.each do |source, arg|
49
- s.gsub! "{#{source}}", arg
50
- end
51
- elsif args.is_a?(Array)
52
- s = sprintf s % args
53
- end
54
- return s
51
+ s
52
+ end
53
+
54
+ def self.getStrings(component, locale)
55
+ SgtnClient.logger.debug "[Translation][getStrings]component=#{component}, locale=#{locale}"
56
+ locale = SgtnClient::LocaleUtil.get_best_locale(locale)
57
+ items = get_cs(component, locale)
58
+ if (items.nil? || items['messages'].nil?) && !LocaleUtil.is_source_locale(locale)
59
+ items = get_cs(component, LocaleUtil.get_source_locale)
55
60
  end
56
61
 
57
- def self.getStrings(component, locale)
58
- SgtnClient.logger.debug "[Translation][getStrings]component=#{component}, locale=#{locale}"
59
- items = get_cs(component, locale)
60
- default = SgtnClient::Config.configurations.default
61
- if items.nil? || items["messages"] == nil
62
- items = {}
63
- s = SgtnClient::Source.getSources(component, default)
64
- if s.nil?
65
- SgtnClient.logger.error "[Translation][getStrings] Missing component: #{component}, locale: #{locale}"
66
- else
67
- default_component, value = s.first
68
- items["component"] = component
69
- items["messages"] = value
70
- items["locale"] = 'source'
71
- end
72
- end
73
- return items
74
- end
62
+ items
63
+ end
75
64
 
65
+ def self.getTranslation(component, key, locale)
66
+ locale = SgtnClient::LocaleUtil.get_best_locale(locale)
67
+ items = get_cs(component, locale)
68
+ items&.dig('messages', key)
69
+ end
76
70
 
77
- private
71
+ def self.get_cs(component, locale)
72
+ cache_item = load_bundle(component, locale)
73
+ cache_item&.dig(:items)
74
+ end
78
75
 
79
- def self.getTranslation(component, key, locale)
80
- items = get_cs(component, locale)
81
- if items.nil? || items["messages"] == nil
82
- nil
83
- else
84
- items["messages"][key]
85
- end
86
- end
76
+ def self.load_bundle(component, locale)
77
+ init_translations unless initialized?
78
+ super
79
+ end
87
80
 
88
- def self.get_cs(component, locale)
89
- flocale = SgtnClient::LocaleUtil.fallback(locale)
90
- cache_key = SgtnClient::CacheUtil.get_cachekey(component, flocale)
91
- SgtnClient.logger.debug "[Translation][get_cs]cache_key=#{cache_key}"
92
- expired, items = SgtnClient::CacheUtil.get_cache(cache_key)
93
- if items.nil? || expired
94
- items = load(component, flocale)
95
- if items.nil?
96
- items = SgtnClient::Source.getSources(component, SgtnClient::Config.configurations.default)
97
- SgtnClient::Core::Cache.put(cache_key, items, 60)
98
- else
99
- SgtnClient::CacheUtil.write_cache(cache_key, items)
100
- end
101
- else
102
- SgtnClient.logger.debug "[Translation]get translations from cache with key: " + cache_key
103
- end
104
-
105
- return items
106
- end
81
+ class << self
82
+ def initialized?
83
+ @initialized ||= false
84
+ end
107
85
 
108
- def self.load(component, locale)
86
+ def init_translations
87
+ # TODO: Lock to initialize?
109
88
  env = SgtnClient::Config.default_environment
110
- mode = SgtnClient::Config.configurations[env]["bundle_mode"]
111
- SgtnClient.logger.debug "[Translation][load]mode=#{mode}"
89
+ mode = SgtnClient::Config.configurations[env]['bundle_mode']
90
+ SgtnClient.logger.debug "[Translation][init_translations]mode=#{mode}"
91
+
112
92
  if mode == 'offline'
113
- return load_o(component, locale)
93
+ extend SgtnClient::TranslationLoader::LocalBundle
114
94
  else
115
- return load_s(component, locale)
95
+ extend SgtnClient::TranslationLoader::ServerBundle
116
96
  end
117
- end
118
97
 
119
- def self.load_o(component, locale)
120
- env = SgtnClient::Config.default_environment
121
- product_name = SgtnClient::Config.configurations[env]["product_name"]
122
- version = SgtnClient::Config.configurations[env]["version"].to_s
123
- translation_bundle = SgtnClient::Config.configurations[env]["translation_bundle"]
124
- bundlepath = translation_bundle + "/" + product_name + "/" + version + "/" + component + "/messages_" + locale + ".json"
125
- SgtnClient::FileUtil.read_json(bundlepath)
126
- end
98
+ extend SgtnClient::TranslationLoader::SourceComparer
99
+ extend SgtnClient::TranslationLoader::Cache
127
100
 
128
- def self.load_s(component, locale)
129
- env = SgtnClient::Config.default_environment
130
- product_name = SgtnClient::Config.configurations[env]["product_name"]
131
- vip_server = SgtnClient::Config.configurations[env]["vip_server"]
132
- version = SgtnClient::Config.configurations[env]["version"].to_s
133
- url = vip_server + "/i18n/api/v2/translation/products/" + product_name + "/versions/" + version + "/locales/" + locale + "/components/" + component+ "?checkTranslationStatus=false&machineTranslation=false&pseudo=false"
134
- begin
135
- obj = SgtnClient::Core::Request.get(url)
136
- rescue => exception
137
- SgtnClient.logger.error exception.message
138
- end
139
- if obj != nil
140
- obj = obj["data"]
141
- end
142
- return obj
101
+ load_translations
102
+ @initialized = true
143
103
  end
144
104
 
145
- end
105
+ def load_translations; end
106
+ end
146
107
 
147
- end
108
+ private_class_method :getTranslation, :get_cs, :load_bundle, :initialized?, :load_translations
109
+ end
110
+ end
@@ -1,4 +1,7 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
1
4
  require 'sgtn-client/cldr/localized_datetime'
2
5
  require 'sgtn-client/cldr/localized_date'
3
6
  require 'sgtn-client/cldr/localized_time'
4
- require 'sgtn-client/cldr/localized_str'
7
+ require 'sgtn-client/cldr/localized_str'
@@ -1,3 +1,6 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
1
4
  require 'date'
2
5
  require 'time'
3
6
 
@@ -24,4 +27,4 @@ Date.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
24
27
  def l_short_s(locale = TwitterCldr.locale)
25
28
  self.to_datetime().localize(locale).to_date().to_short_s
26
29
  end
27
- LOCALIZE
30
+ LOCALIZE
@@ -1,3 +1,6 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
1
4
  require 'date'
2
5
  require 'time'
3
6
 
@@ -60,4 +63,4 @@ DateTime.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
60
63
  tz.display_name_for(self, display_name)
61
64
  end
62
65
  end
63
- LOCALIZE
66
+ LOCALIZE
@@ -1,3 +1,5 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
1
3
 
2
4
  String.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
3
5
  def to_plural_s(locale, arg)
@@ -8,4 +10,4 @@ String.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
8
10
  num_str
9
11
  end
10
12
  end
11
- LOCALIZE
13
+ LOCALIZE
@@ -1,3 +1,6 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
1
4
  require 'date'
2
5
  require 'time'
3
6
 
@@ -24,4 +27,4 @@ Time.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
24
27
  def l_short_s(locale = TwitterCldr.locale)
25
28
  self.localize(locale).to_short_s
26
29
  end
27
- LOCALIZE
30
+ LOCALIZE
@@ -0,0 +1,33 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
4
+ module SgtnClient
5
+ class SingleOperation
6
+ def initialize(*conditions, &block)
7
+ raise 'no way to create a new obj' unless block
8
+
9
+ @lock = Mutex.new
10
+ @hash = {}
11
+
12
+ @conditions = conditions
13
+ @creator = block
14
+ end
15
+
16
+ # return new created object
17
+ def operate(id, *args)
18
+ @lock.synchronize do
19
+ obj = @hash[id]
20
+ @conditions.each do |con|
21
+ return obj unless con.call(id, obj, *args)
22
+ end
23
+ @hash[id] = @creator.call(id, obj, *args)
24
+ end
25
+ end
26
+
27
+ def remove_object(id)
28
+ @lock.synchronize do
29
+ @hash.delete(id)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -1,99 +1,33 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
1
4
  require 'date'
2
5
 
3
6
  module SgtnClient::Core
4
7
  class Cache
5
- Entry = Struct.new(:expiry, :value)
8
+ Entry = Struct.new(:expiry, :items)
6
9
 
7
10
  def self.initialize(disabled=false, opts={})
8
11
  @@opts = opts
9
- @mutex = Mutex.new
10
- if disabled == false
11
- @@data = Hash.new
12
- SgtnClient.logger.debug "[Cache][initialize]cache is enabled!"
13
- else
14
- @@data = nil
15
- SgtnClient.logger.debug "[Cache][initialize]cache is disabled!"
16
- end
17
- end
18
-
19
- def self.keys
20
- if @@data == nil
21
- return nil
22
- end
23
- SgtnClient.logger.debug "[Cache][keys]get cache keys"
24
- @@data.keys
12
+ SgtnClient.logger.debug "[Cache][initialize] Disable cache? #{disabled}"
13
+ @@data = Hash.new
25
14
  end
26
15
 
27
16
  def self.get(key)
28
- if @@data == nil
29
- return nil, nil
30
- end
31
17
  SgtnClient.logger.debug "[Cache][get]get cache for key: " + key
32
- invalidate(key)
33
- end
34
-
35
- def self.has(key)
36
- if @@data == nil
37
- return nil
38
- end
39
- SgtnClient.logger.debug "[Cache][has]check if the cache has key: #{(@@data.has_key? key)}"
40
- @@data.has_key? key
18
+ return @@data&.dig(key)
41
19
  end
42
20
 
43
- def self.put(key, value, ttl=nil)
44
- @mutex.synchronize do
45
- if @@data == nil || value == nil
46
- return nil
47
- end
48
- ttl ||= @@opts[:ttl]
49
- # hours from new
50
- SgtnClient.logger.debug "[Cache][put]put cache for key '" + key + "' with expired time at'" + (Time.now + ttl*60).to_s
51
- @@data[key] = Entry.new(Time.now + ttl*60, value)
52
- end
53
- end
54
-
55
- def self.delete(key)
56
- @mutex.synchronize do
57
- if @@data == nil
58
- return nil
59
- end
60
- SgtnClient.logger.debug "[Cache][delete]delete cache for key: " + key
61
- @@data.delete key
62
- end
21
+ def self.put(key, items, ttl=nil)
22
+ ttl ||= @@opts[:ttl]
23
+ # hours from new
24
+ SgtnClient.logger.debug "[Cache][put]put cache for key '" + key + "' with expired time at'" + (Time.now + ttl*60).to_s
25
+ @@data[key] = Entry.new(Time.now + ttl*60, items)
63
26
  end
64
27
 
65
28
  def self.clear
66
- @mutex.synchronize do
67
- if @@data == nil
68
- return nil
69
- end
70
- SgtnClient.logger.debug "[Cache][clear]clear cache!"
71
- @@data = Hash.new
72
- end
73
- end
74
-
75
- def self.invalidate(key)
76
- @mutex.synchronize do
77
- if @@data == nil
78
- return nil, nil
79
- end
80
- SgtnClient.logger.debug "[Cache][invalidate]invalidate expired cache......"
81
- now = Time.now
82
- if has(key)
83
- v = @@data[key]
84
- expired = false
85
- SgtnClient.logger.debug "[Cache][invalidate]check cache: key=#{key}, expiredtime=#{v[:expiry]}, now=#{now}, expired=#{(v[:expiry] < now)}"
86
- if v[:expiry] < now
87
- SgtnClient.logger.debug "[Cache][invalidate]before deleting the cache: data=#{@@data}"
88
- @@data.delete(key)
89
- SgtnClient.logger.debug "[Cache][invalidate]after deleting the cache: data=#{@@data}"
90
- expired = true
91
- end
92
- return expired, v[:value]
93
- else
94
- return nil, nil
95
- end
96
- end
29
+ SgtnClient.logger.debug "[Cache][clear]clear cache!"
30
+ @@data = Hash.new
97
31
  end
98
32
  end
99
33
 
@@ -1,3 +1,6 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
1
4
  require 'erb'
2
5
  require 'yaml'
3
6
 
@@ -163,4 +166,4 @@ module SgtnClient
163
166
  end
164
167
  end
165
168
 
166
- end
169
+ end
@@ -1,3 +1,6 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
1
4
  require 'multi_json'
2
5
  require 'pp'
3
6
 
@@ -1,3 +1,6 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
1
4
  require 'logger'
2
5
 
3
6
  module SgtnClient
@@ -47,4 +50,3 @@ module SgtnClient
47
50
  end
48
51
 
49
52
  end
50
-
@@ -1,3 +1,6 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
1
4
  require 'rest-client'
2
5
  require 'multi_json'
3
6
 
@@ -18,4 +21,4 @@ module SgtnClient::Core
18
21
  return obj
19
22
  end
20
23
  end
21
- end
24
+ end
@@ -1,3 +1,6 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
1
4
  require 'json'
2
5
 
3
6
  module SgtnClient
@@ -35,4 +38,4 @@ module SgtnClient
35
38
  end
36
39
  end
37
40
  end
38
- end
41
+ end
@@ -0,0 +1,47 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
4
+ module SgtnClient
5
+ autoload :CacheUtil, 'sgtn-client/util/cache-util'
6
+ autoload :SingleOperation, 'sgtn-client/common/single_operation'
7
+ end
8
+ module SgtnClient::TranslationLoader::Cache
9
+ def load_bundle(component, locale)
10
+ cache_key = SgtnClient::CacheUtil.get_cachekey(component, locale)
11
+ SgtnClient.logger.debug "[#{self.to_s}][#{__FILE__}][#{__method__}] cache_key=#{cache_key}"
12
+ cache_item = SgtnClient::CacheUtil.get_cache(cache_key)
13
+ if cache_item.nil?
14
+ # refresh synchronously if not in cache
15
+ SgtnClient.logger.debug "[#{self.to_s}][#{__FILE__}][#{__method__}] Cache miss. cache_key=#{cache_key}"
16
+ cache_item = (single_loader { |c, l| super(c, l) }).operate(cache_key, component, locale).value
17
+ # TODO: if an error occurs when requesting a bundle, need to avoid more requests
18
+ elsif SgtnClient::CacheUtil.is_expired(cache_item) && locale != SgtnClient::LocaleUtil.get_source_locale # local source never expires.
19
+ SgtnClient.logger.debug "[#{self.to_s}][#{__FILE__}][#{__method__}] Bundle cache is expired. cache_key=#{cache_key}"
20
+ @single_loader.operate(cache_key, component, locale) # refresh in background
21
+ end
22
+ cache_item
23
+ end
24
+
25
+ private
26
+
27
+ def single_loader
28
+ @single_loader ||= begin
29
+ none_alive = proc { |_, thread| thread.nil? || thread.alive? == false }
30
+ to_run = proc do |id|
31
+ cache_item = SgtnClient::CacheUtil.get_cache(id)
32
+ cache_item&.dig(:items).nil? || SgtnClient::CacheUtil.is_expired(cache_item)
33
+ end
34
+ creator = proc do |id, _, c, l|
35
+ Thread.new do
36
+ SgtnClient.logger.debug "Refreshing cache for #{c}/#{l}"
37
+ cache_item = SgtnClient::CacheUtil.write_cache(id, yield(c, l))
38
+ # delete thread from hash after finish
39
+ Thread.new { @single_loader.remove_object(id) }
40
+ cache_item
41
+ end
42
+ end
43
+
44
+ SgtnClient::SingleOperation.new(none_alive, to_run, &creator)
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,13 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
4
+ module SgtnClient::TranslationLoader::LocalBundle
5
+ def load_bundle(component, locale)
6
+ env = SgtnClient::Config.default_environment
7
+ product_name = SgtnClient::Config.configurations[env]['product_name']
8
+ version = SgtnClient::Config.configurations[env]['version'].to_s
9
+ translation_bundle = SgtnClient::Config.configurations[env]['translation_bundle']
10
+ bundlepath = translation_bundle + '/' + product_name + '/' + version + '/' + component + '/messages_' + locale + '.json'
11
+ SgtnClient::FileUtil.read_json(bundlepath)
12
+ end
13
+ end
@@ -0,0 +1,29 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
4
+ module SgtnClient
5
+ class Source
6
+ def self.load_bundle(component)
7
+ SgtnClient.logger.debug "[Source][getBundle]component=#{component}"
8
+ env = SgtnClient::Config.default_environment
9
+ source_bundle = SgtnClient::Config.configurations[env]['source_bundle']
10
+ component_path = "#{source_bundle}/#{component}"
11
+ total_messages = nil
12
+ Dir.glob('**/*.{yml, yaml}', base: component_path) do |f|
13
+ bundle = SgtnClient::FileUtil.read_yml("#{component_path}/#{f}")
14
+ if total_messages.nil?
15
+ total_messages = bundle&.first&.last
16
+ else
17
+ total_messages.merge!(bundle&.first&.last)
18
+ end
19
+ end
20
+
21
+ if total_messages
22
+ return { 'component' => component, 'locale' => SgtnClient::LocaleUtil.get_source_locale, 'messages' => total_messages }
23
+ end
24
+ rescue StandardError => e
25
+ SgtnClient.logger.error e.message
26
+ nil
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,22 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
4
+ module SgtnClient::Core
5
+ autoload :Request, 'sgtn-client/core/request'
6
+ end
7
+
8
+ module SgtnClient::TranslationLoader::ServerBundle
9
+ def load_bundle(component, locale)
10
+ env = SgtnClient::Config.default_environment
11
+ product_name = SgtnClient::Config.configurations[env]['product_name']
12
+ vip_server = SgtnClient::Config.configurations[env]['vip_server']
13
+ version = SgtnClient::Config.configurations[env]['version'].to_s
14
+ url = vip_server + '/i18n/api/v2/translation/products/' + product_name + '/versions/' + version + '/locales/' + locale + '/components/' + component + '?checkTranslationStatus=false&machineTranslation=false&pseudo=false'
15
+ begin
16
+ obj = SgtnClient::Core::Request.get(url)
17
+ rescue StandardError => e
18
+ SgtnClient.logger.error e.message
19
+ end
20
+ obj && obj['data']
21
+ end
22
+ end
@@ -0,0 +1,38 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
4
+ module SgtnClient
5
+ autoload :Source, 'sgtn-client/loader/local_source_bundle'
6
+ end
7
+ module SgtnClient::TranslationLoader::SourceComparer
8
+ def load_bundle(component, locale)
9
+ # source locale always uses source bundles
10
+ return SgtnClient::Source.load_bundle(component) if SgtnClient::LocaleUtil.is_source_locale(locale)
11
+
12
+ translation_bundle_thread = Thread.new { super(component, locale) }
13
+ old_source_bundle = super(component, SgtnClient::LocaleUtil.get_source_locale)
14
+ source_bundle = get_cs(component, SgtnClient::LocaleUtil.get_source_locale)
15
+ translation_bundle = translation_bundle_thread.value
16
+
17
+ compare_source(translation_bundle, old_source_bundle, source_bundle)
18
+ end
19
+
20
+ private
21
+
22
+ def compare_source(translation_bundle, old_source_bundle, source_bundle)
23
+ return translation_bundle if translation_bundle.nil? || source_bundle.nil? || old_source_bundle.nil?
24
+
25
+ old_source_messages = old_source_bundle['messages']
26
+ translation_messages = translation_bundle['messages']
27
+ translation_bundle['messages'] = new_translation_messages = {}
28
+ source_bundle['messages'].each do |key, value|
29
+ translation = translation_messages[key]
30
+ new_translation_messages[key] = if old_source_messages[key] == value && !translation.nil?
31
+ translation
32
+ else
33
+ SgtnClient::StringUtil.new(value, SgtnClient::LocaleUtil.get_source_locale)
34
+ end
35
+ end
36
+ translation_bundle
37
+ end
38
+ end
@@ -1,4 +1,9 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
1
4
  module SgtnClient
5
+ LOGFILE_SHIFT_AGE = 4
6
+
2
7
  module Core
3
8
  autoload :Cache, "sgtn-client/core/cache"
4
9
  end
@@ -44,7 +49,7 @@ module SgtnClient
44
49
  end
45
50
  file = File.open(file, 'a')
46
51
  file.sync = true
47
- SgtnClient.logger = Logger.new(file)
52
+ SgtnClient.logger = Logger.new(file, LOGFILE_SHIFT_AGE)
48
53
 
49
54
  # Set log level for sandbox mode
50
55
  env = SgtnClient::Config.default_environment
@@ -1,51 +1,43 @@
1
- require 'erb'
2
- require 'yaml'
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
3
 
4
4
  module SgtnClient
5
-
6
5
  module Core
7
- autoload :Cache, "sgtn-client/core/cache"
6
+ autoload :Cache, 'sgtn-client/core/cache'
8
7
  end
9
-
8
+
10
9
  class CacheUtil
10
+ def self.get_cache(cache_key)
11
+ SgtnClient.logger.debug "[CacheUtil]get cache with key #{cache_key}"
12
+ SgtnClient::Core::Cache.get(cache_key)
13
+ end
11
14
 
12
- def self.get_cache(cache_key)
13
- expired, items = SgtnClient::Core::Cache.get(cache_key)
14
- SgtnClient.logger.debug "[CacheUtil]get cache with key #{cache_key}, expired #{expired}"
15
- return expired, items
16
- end
17
-
18
- def self.clear_cache()
19
- SgtnClient::Core::Cache.clear()
20
- SgtnClient.logger.debug "[CacheUtil]clear cache"
21
- end
22
-
23
- def self.write_cache(cache_key, items)
24
- if items.nil?
25
- return nil
26
- end
27
- env = SgtnClient::Config.default_environment
28
- cache_expiry_period = SgtnClient::Config.configurations[env]["cache_expiry_period"]
29
- # expired after 24 hours
30
- if cache_expiry_period == nil
31
- cache_expiry_period = 24*60
32
- end
33
- SgtnClient.logger.debug "[CacheUtil]write cache with key #{cache_key}, cache_expiry_period #{cache_expiry_period}, itmes #{items}"
34
- SgtnClient::Core::Cache.put(cache_key, items, cache_expiry_period)
35
- end
36
-
37
- def self.get_cachekey(component, locale)
38
- env = SgtnClient::Config.default_environment
39
- product_name = SgtnClient::Config.configurations[env]["product_name"]
40
- version = SgtnClient::Config.configurations[env]["version"].to_s
41
- default_l = SgtnClient::Config.configurations[env]["default_language"]
42
- if default_l == nil
43
- default_l = 'en'
44
- end
45
- lc = locale == default_l ? SgtnClient::Config.configurations.default: locale
46
- SgtnClient.logger.debug "[CacheUtil]get cache key: #{lc}"
47
- return product_name + "_" + version + "_" + component + "_" + lc
48
- end
49
- end
15
+ def self.clear_cache
16
+ SgtnClient::Core::Cache.clear
17
+ SgtnClient.logger.debug '[CacheUtil]clear cache'
18
+ end
19
+
20
+ def self.write_cache(cache_key, items)
21
+ return nil if items.nil? || items.empty?
50
22
 
51
- end
23
+ env = SgtnClient::Config.default_environment
24
+ cache_expiry_period = SgtnClient::Config.configurations[env]['cache_expiry_period']
25
+ # expired after 24 hours
26
+ cache_expiry_period = 24 * 60 if cache_expiry_period.nil?
27
+ SgtnClient.logger.debug "[CacheUtil]write cache with key #{cache_key}, cache_expiry_period #{cache_expiry_period}"
28
+ SgtnClient::Core::Cache.put(cache_key, items, cache_expiry_period)
29
+ end
30
+
31
+ def self.get_cachekey(component, locale)
32
+ env = SgtnClient::Config.default_environment
33
+ product_name = SgtnClient::Config.configurations[env]['product_name']
34
+ version = SgtnClient::Config.configurations[env]['version'].to_s
35
+ product_name + '_' + version + '_' + component + '_' + locale
36
+ end
37
+
38
+ def self.is_expired(cache_item)
39
+ cache_item[:expiry] < Time.now
40
+ end
41
+
42
+ end
43
+ end
@@ -1,34 +1,24 @@
1
- require 'erb'
2
- require 'yaml'
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
4
+ autoload :YAML, 'yaml'
5
+ autoload :MultiJson, 'multi_json'
3
6
 
4
7
  module SgtnClient
5
8
 
6
9
  class FileUtil
7
-
8
- @mutex = Mutex.new
9
-
10
10
  def self.read_json(bundlepath)
11
11
  SgtnClient.logger.debug "[FileUtil]read json file from: " + bundlepath
12
- @mutex.synchronize do
13
- data_hash = nil
14
- begin
15
- file = File.read(bundlepath)
16
- data_hash = MultiJson.load(file)
17
- rescue => exception
18
- SgtnClient.logger.error exception.message
19
- end
20
- return data_hash
12
+ begin
13
+ return MultiJson.load(File.read(bundlepath))
14
+ rescue => exception
15
+ SgtnClient.logger.error exception.message
21
16
  end
17
+ nil
22
18
  end
23
19
 
24
20
  def self.read_yml(file_name)
25
- SgtnClient.logger.debug "[FileUtil]read yml file from: " + file_name
26
- @mutex.synchronize do
27
- erb = ERB.new(File.read(file_name))
28
- erb.filename = file_name
29
- YAML.load(erb.result)
30
- end
21
+ YAML::load(File.read(file_name))
31
22
  end
32
23
  end
33
-
34
- end
24
+ end
@@ -1,31 +1,48 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+ require 'set'
4
+
1
5
  module SgtnClient
6
+ SUPPORTED_LOCALES = %w[en de es fr ko ja zh-Hans zh-Hant zh de-CH].freeze # TODO get this from service in online mode
7
+
8
+ MAP_LOCALES = {
9
+ 'zh-CN' => 'zh-Hans',
10
+ 'zh-TW' => 'zh-Hant',
11
+ 'zh-Hans-CN' => 'zh-Hans',
12
+ 'zh-Hant-TW' => 'zh-Hant'
13
+ }.freeze
14
+
15
+ class LocaleUtil
16
+ def self.get_best_locale(locale)
17
+ return get_default_locale if locale.nil?
18
+
19
+ locale = locale.to_s
20
+ return get_default_locale if locale.empty?
21
+
22
+ get_best_match(locale)
23
+ end
24
+
25
+ def self.is_source_locale(locale = nil)
26
+ locale == get_source_locale
27
+ end
28
+
29
+ def self.get_best_match(locale)
30
+ locale = locale.gsub('_', '-')
31
+ locale = SgtnClient::MAP_LOCALES[locale] if SgtnClient::MAP_LOCALES.key?(locale)
32
+ return locale if SUPPORTED_LOCALES.include?(locale)
33
+ return LocaleUtil.get_source_locale if locale.index('-').nil?
34
+ get_best_match(locale.slice(0..(locale.rindex('-')-1)) )
35
+ end
2
36
 
3
- DEFAULT_LOCALES = ['en', 'de', 'es', 'fr', 'ko', 'ja', 'zh-Hans', 'zh-Hant']
4
-
5
- MAP_LOCALES = {
6
- "zh-CN" =>"zh-Hans",
7
- "zh-TW" =>"zh-Hant",
8
- "zh-Hans-CN" =>"zh-Hans",
9
- "zh-Hant-TW" =>"zh-Hant",
10
- }
11
-
12
- class LocaleUtil
13
- def self.fallback(locale)
14
- found = SgtnClient::DEFAULT_LOCALES.select {|e| e == locale}
15
- if !found.empty?
16
- return found[0]
17
- end
18
- if SgtnClient::MAP_LOCALES.key?(locale)
19
- return SgtnClient::MAP_LOCALES[locale]
20
- end
21
- parts = locale.split("-")
22
- if parts.size > 1
23
- f = SgtnClient::DEFAULT_LOCALES.select {|e| e == parts[0]}
24
- if !f.empty?
25
- return f[0]
26
- end
27
- end
28
- return locale
29
- end
37
+ def self.get_source_locale
38
+ 'en'
30
39
  end
31
- end
40
+
41
+ def self.get_default_locale
42
+ env = SgtnClient::Config.default_environment
43
+ SgtnClient::Config.configurations[env]['default_language'] || 'en'
44
+ end
45
+
46
+ private_class_method :get_best_match
47
+ end
48
+ end
@@ -0,0 +1,12 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
4
+ module SgtnClient
5
+ class StringUtil < String
6
+ def initialize(str, locale)
7
+ super(str)
8
+ @locale = locale
9
+ end
10
+ attr_accessor :locale
11
+ end
12
+ end
@@ -1,3 +1,5 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
1
3
 
2
4
  module SgtnClient
3
5
 
@@ -40,4 +42,4 @@ module SgtnClient
40
42
 
41
43
  end
42
44
 
43
- end
45
+ end
@@ -1,3 +1,6 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
1
4
  require "sgtn-client/sgtn-client"
2
5
  require 'sgtn-client/cldr/core_ext'
3
6
  require 'twitter_cldr'
data/lib/version.rb CHANGED
@@ -1,3 +1,5 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
1
3
 
2
4
  VERSION_INFO = [0, 2, 1].freeze
3
5
  VERSION = VERSION_INFO.map(&:to_s).join('.').freeze
metadata CHANGED
@@ -1,29 +1,15 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: singleton-client-test
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.7.0.30
4
+ version: 0.7.0.33
5
5
  platform: ruby
6
6
  authors:
7
7
  - VMware G11n Team
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-02-15 00:00:00.000000000 Z
11
+ date: 2022-03-30 00:00:00.000000000 Z
12
12
  dependencies:
13
- - !ruby/object:Gem::Dependency
14
- name: rest-client
15
- requirement: !ruby/object:Gem::Requirement
16
- requirements:
17
- - - "~>"
18
- - !ruby/object:Gem::Version
19
- version: '2.0'
20
- type: :development
21
- prerelease: false
22
- version_requirements: !ruby/object:Gem::Requirement
23
- requirements:
24
- - - "~>"
25
- - !ruby/object:Gem::Version
26
- version: '2.0'
27
13
  - !ruby/object:Gem::Dependency
28
14
  name: multi_json
29
15
  requirement: !ruby/object:Gem::Requirement
@@ -94,34 +80,6 @@ dependencies:
94
80
  - - "~>"
95
81
  - !ruby/object:Gem::Version
96
82
  version: '3.0'
97
- - !ruby/object:Gem::Dependency
98
- name: pry
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '0'
111
- - !ruby/object:Gem::Dependency
112
- name: pry-doc
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '0'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '0'
125
83
  - !ruby/object:Gem::Dependency
126
84
  name: rdoc
127
85
  requirement: !ruby/object:Gem::Requirement
@@ -244,6 +202,20 @@ dependencies:
244
202
  - - "~>"
245
203
  - !ruby/object:Gem::Version
246
204
  version: '1.0'
205
+ - !ruby/object:Gem::Dependency
206
+ name: rest-client
207
+ requirement: !ruby/object:Gem::Requirement
208
+ requirements:
209
+ - - "~>"
210
+ - !ruby/object:Gem::Version
211
+ version: '2.0'
212
+ type: :runtime
213
+ prerelease: false
214
+ version_requirements: !ruby/object:Gem::Requirement
215
+ requirements:
216
+ - - "~>"
217
+ - !ruby/object:Gem::Version
218
+ version: '2.0'
247
219
  - !ruby/object:Gem::Dependency
248
220
  name: twitter_cldr
249
221
  requirement: !ruby/object:Gem::Requirement
@@ -274,16 +246,23 @@ files:
274
246
  - lib/sgtn-client/cldr/localized_datetime.rb
275
247
  - lib/sgtn-client/cldr/localized_str.rb
276
248
  - lib/sgtn-client/cldr/localized_time.rb
249
+ - lib/sgtn-client/common/single_operation.rb
277
250
  - lib/sgtn-client/core/cache.rb
278
251
  - lib/sgtn-client/core/config.rb
279
252
  - lib/sgtn-client/core/exceptions.rb
280
253
  - lib/sgtn-client/core/logging.rb
281
254
  - lib/sgtn-client/core/request.rb
282
255
  - lib/sgtn-client/formatters/plurals/plural_formatter.rb
256
+ - lib/sgtn-client/loader/cache.rb
257
+ - lib/sgtn-client/loader/local_bundle.rb
258
+ - lib/sgtn-client/loader/local_source_bundle.rb
259
+ - lib/sgtn-client/loader/server_bundle.rb
260
+ - lib/sgtn-client/loader/source_comparer.rb
283
261
  - lib/sgtn-client/sgtn-client.rb
284
262
  - lib/sgtn-client/util/cache-util.rb
285
263
  - lib/sgtn-client/util/file-util.rb
286
264
  - lib/sgtn-client/util/locale-util.rb
265
+ - lib/sgtn-client/util/string-util.rb
287
266
  - lib/sgtn-client/util/validate-util.rb
288
267
  - lib/singleton-ruby.rb
289
268
  - lib/version.rb