singleton-client-test 0.7.0.30 → 0.7.0.33

Sign up to get free protection for your applications and to get access to all the features.
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