singleton-client-test 0.7.0.32 → 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: 7c3518e9f8e872dd00acd151a9157c273f274c5398d773c42e75d07e0667413b
4
- data.tar.gz: 0eec546d1df60f066a1f346c04da0cac374f1944980477ccb32b5055a70e62b0
3
+ metadata.gz: a2a32a268d9bc9b395baeb2d296049cbbb29a40c081968d6e8a5ae364c39444c
4
+ data.tar.gz: fdf427aaf792fbff1bf6afa404d6e0aeeea030b9fa90b7eab578cbe46659656e
5
5
  SHA512:
6
- metadata.gz: b8eb7e6e83057a56fa3a0d618b14ef83e61458319ccbbea388028961bbeae0ea061c82c87ed34f89cfe43c2336fc390b4ffe6801c1e9e6c85e43a2c4dd366e9f
7
- data.tar.gz: 10eb576187a7ff47e04e409ff292862397e956de6adfbe9f2a39565cd5219c22397a959a23b399c96627aeab85562992f0abc92edec3a590f0ec7a7b610c4794
6
+ metadata.gz: 1ecfa3b8fbc1ef494e41a517a102856f4717d408845eeac43cd751c24df2a590404082cd00670b280fd8c404b3dd95ecd2ae5c06f7b0c0b23172b9eb7ab2fff7
7
+ data.tar.gz: 0a8aee2dd03eaa02c981cdfaa097ffbddebc2118c7c7a63625ad19ca332ecf582fac19a812339ef9920dac37765a03b30d9800d69cfe9dd2b854762ee0796170
@@ -1,73 +1,24 @@
1
1
  # Copyright 2022 VMware, Inc.
2
2
  # SPDX-License-Identifier: EPL-2.0
3
3
 
4
+ require 'sgtn-client/loader/local_source_bundle'
5
+
4
6
  module SgtnClient
5
-
6
- autoload :CacheUtil, "sgtn-client/util/cache-util"
7
+ autoload :CacheUtil, 'sgtn-client/util/cache-util'
7
8
 
8
9
  class Source
9
-
10
- def self.getSource(component, key, locale)
11
- SgtnClient.logger.debug "[Source][getSource]component=#{component}, key=#{key}, locale=#{locale}"
12
- cache_key = SgtnClient::CacheUtil.get_cachekey(component, locale)
13
- expired, items = SgtnClient::CacheUtil.get_cache(cache_key)
14
- if items.nil?
15
- items = getBundle(component, locale)
16
- SgtnClient::CacheUtil.write_cache(cache_key, items)
17
- else
18
- SgtnClient.logger.debug "[Source][getSource]getting sources from cache with key: " + cache_key
19
- end
20
- s = (items.nil? || items[locale].nil?)? nil : items[locale][key]
21
- if items.nil? || s.nil?
22
- SgtnClient.logger.debug "[Source][getSource]source not found, return key: " + key
23
- #return key
24
- return nil
25
- else
26
- return s
27
- end
28
- end
29
-
30
- def self.getSources(component, locale)
31
- SgtnClient.logger.debug "[Source][getSources]component=#{component}, locale=#{locale}"
32
- cache_key = SgtnClient::CacheUtil.get_cachekey(component, locale)
33
- expired, items = SgtnClient::CacheUtil.get_cache(cache_key)
34
- if items.nil? || expired
35
- items = getBundle(component, locale)
36
- SgtnClient::CacheUtil.write_cache(cache_key, items)
37
- else
38
- SgtnClient.logger.debug "[Source][getSources]getting sources from cache with key: " + cache_key
39
- end
40
- return items
41
- end
42
-
43
- def self.loadBundles(locale)
44
- SgtnClient.logger.debug "[Source][loadBundles]locale=#{locale}"
45
- env = SgtnClient::Config.default_environment
46
- SgtnClient::Config.configurations.default = locale
47
- source_bundle = SgtnClient::Config.configurations[env]["source_bundle"]
48
- Dir.foreach(source_bundle) do |component|
49
- next if component == '.' || component == '..'
50
- yamlfile = File.join(source_bundle, component + "/" + locale + ".yml")
51
- bundle = SgtnClient::FileUtil.read_yml(yamlfile)
52
- cachekey = SgtnClient::CacheUtil.get_cachekey(component, locale)
53
- SgtnClient::CacheUtil.write_cache(cachekey,bundle)
54
- end
55
- end
56
-
57
- private
58
- def self.getBundle(component, locale)
59
- SgtnClient.logger.debug "[Source][getBundle]component=#{component}, locale=#{locale}"
60
- env = SgtnClient::Config.default_environment
61
- source_bundle = SgtnClient::Config.configurations[env]["source_bundle"]
62
- bundlepath = source_bundle + "/" + component + "/" + locale + ".yml"
63
- begin
64
- bundle = SgtnClient::FileUtil.read_yml(bundlepath)
65
- rescue => exception
66
- SgtnClient.logger.error exception.message
67
- end
68
- 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)
69
21
  end
70
-
22
+ end
71
23
  end
72
-
73
24
  end
@@ -2,24 +2,23 @@
2
2
  # SPDX-License-Identifier: EPL-2.0
3
3
 
4
4
  module SgtnClient
5
- class T < Translation
6
-
7
- def self.s(key)
8
- locale = RequestStore.store[:locale]
9
- component = RequestStore.store[:component]
10
- return getString(component, key, locale)
11
- end
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
12
11
 
13
- def self.s_f(key, args)
14
- locale = RequestStore.store[:locale]
15
- component = RequestStore.store[:component]
16
- return getString_f(component, key, args, locale)
17
- 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
18
17
 
19
- def self.c()
20
- locale = RequestStore.store[:locale]
21
- component = RequestStore.store[:component]
22
- return getStrings(component, locale)
23
- end
18
+ def self.c
19
+ locale = RequestStore.store[:locale]
20
+ component = RequestStore.store[:component]
21
+ Translation.getStrings(component, locale)
24
22
  end
23
+ end
25
24
  end
@@ -1,158 +1,110 @@
1
1
  # Copyright 2022 VMware, Inc.
2
2
  # SPDX-License-Identifier: EPL-2.0
3
3
 
4
- require 'multi_json'
5
-
6
4
  module SgtnClient
7
-
8
- module Core
9
- autoload :Request, "sgtn-client/core/request"
10
- autoload :Cache, "sgtn-client/core/cache"
11
- autoload :CacheUtil, "sgtn-client/util/cache-util"
12
- 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'
13
13
  end
14
-
15
- class Translation
16
-
17
- def self.getString(component, key, locale)
18
- SgtnClient.logger.debug "[Translation.getString]component: #{component}, key: #{key}, locale: #{locale}"
19
- str = getTranslation(component, key, locale)
20
- if str.nil?
21
- str = SgtnClient::Source.getSource(component, key, SgtnClient::Config.configurations.default)
22
- if str.nil?
23
- SgtnClient.logger.debug "[Translation][getString] Missing source string with key: #{key}, component: #{component}, locale: #{locale}"
24
- end
25
- end
26
- str
27
- end
28
14
 
29
- def self.getString_p(component, key, plural_args, locale)
30
- SgtnClient.logger.debug "[Translation][getString_p]component=#{component}, key=#{key}, locale=#{locale}"
31
- str = getTranslation(component, key, locale)
32
- if str.nil?
33
- str = SgtnClient::Source.getSource(component, key, SgtnClient::Config.configurations.default)
34
- if str.nil?
35
- SgtnClient.logger.debug "[Translation][getString_p] Missing source string with key: #{key}, component: #{component}, locale: #{locale}"
36
- return nil
37
- end
38
- str.to_plural_s(:en, plural_args)
39
- else
40
- str.to_plural_s(locale, plural_args)
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
41
32
  end
33
+ else
34
+ locale = str.locale if str.is_a?(SgtnClient::StringUtil)
35
+ str.to_plural_s(locale, plural_args)
42
36
  end
37
+ end
43
38
 
44
- def self.getString_f(component, key, args, locale, *optionals)
45
- SgtnClient.logger.debug "[Translation][getString_f]component=#{component}, key=#{key}, locale=#{locale}"
46
- s = getString(component, key, locale, *optionals)
47
- if s.nil?
48
- return nil
49
- end
50
- if args.is_a?(Hash)
51
- args.each do |source, arg|
52
- s.gsub! "{#{source}}", arg
53
- end
54
- elsif args.is_a?(Array)
55
- s = sprintf s % args
56
- end
57
- return s
58
- end
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?
59
43
 
60
- def self.getStrings(component, locale)
61
- SgtnClient.logger.debug "[Translation][getStrings]component=#{component}, locale=#{locale}"
62
- locale = SgtnClient::LocaleUtil.get_best_locale(locale)
63
- items = get_cs(component, locale)
64
- default = SgtnClient::Config.configurations.default
65
- if items.nil? || items["messages"] == nil
66
- items = {}
67
- s = SgtnClient::Source.getSources(component, default)
68
- if s.nil?
69
- SgtnClient.logger.error "[Translation][getStrings] Missing component: #{component}, locale: #{locale}"
70
- else
71
- default_component, value = s.first
72
- items["component"] = component
73
- items["messages"] = value
74
- items["locale"] = 'source'
75
- end
44
+ if args.is_a?(Hash)
45
+ args.each do |source, arg|
46
+ s.gsub! "{#{source}}", arg
76
47
  end
77
- return items
78
- end
79
-
48
+ elsif args.is_a?(Array)
49
+ s = s % args
50
+ end
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)
60
+ end
80
61
 
81
- private
62
+ items
63
+ end
82
64
 
83
- def self.getTranslation(component, key, locale)
84
- locale = SgtnClient::LocaleUtil.get_best_locale(locale)
85
- items = get_cs(component, locale)
86
- if items.nil? || items["messages"] == nil
87
- nil
88
- else
89
- items["messages"][key]
90
- end
91
- end
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
92
70
 
93
- def self.get_cs(component, locale)
94
- # source locale always return source bundle
95
- if locale == LocaleUtil.get_source_locale
96
- sources = SgtnClient::Source.getSources(component, SgtnClient::Config.configurations.default)
97
- messages = sources&.first&.last
98
- return {'locale' => locale, 'component' => component, 'messages' => messages} if messages
99
- end
71
+ def self.get_cs(component, locale)
72
+ cache_item = load_bundle(component, locale)
73
+ cache_item&.dig(:items)
74
+ end
100
75
 
101
- cache_key = SgtnClient::CacheUtil.get_cachekey(component, locale)
102
- SgtnClient.logger.debug "[Translation][get_cs]cache_key=#{cache_key}"
103
- expired, items = SgtnClient::CacheUtil.get_cache(cache_key)
104
- if items.nil? || expired
105
- items = load(component, locale)
106
- if items.nil?
107
- items = SgtnClient::Source.getSources(component, SgtnClient::Config.configurations.default)
108
- SgtnClient::Core::Cache.put(cache_key, items, 60)
109
- else
110
- SgtnClient::CacheUtil.write_cache(cache_key, items)
111
- end
112
- else
113
- SgtnClient.logger.debug "[Translation]get translations from cache with key: " + cache_key
114
- end
76
+ def self.load_bundle(component, locale)
77
+ init_translations unless initialized?
78
+ super
79
+ end
115
80
 
116
- return items
117
- end
81
+ class << self
82
+ def initialized?
83
+ @initialized ||= false
84
+ end
118
85
 
119
- def self.load(component, locale)
86
+ def init_translations
87
+ # TODO: Lock to initialize?
120
88
  env = SgtnClient::Config.default_environment
121
- mode = SgtnClient::Config.configurations[env]["bundle_mode"]
122
- 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
+
123
92
  if mode == 'offline'
124
- return load_o(component, locale)
93
+ extend SgtnClient::TranslationLoader::LocalBundle
125
94
  else
126
- return load_s(component, locale)
95
+ extend SgtnClient::TranslationLoader::ServerBundle
127
96
  end
128
- end
129
97
 
130
- def self.load_o(component, locale)
131
- env = SgtnClient::Config.default_environment
132
- product_name = SgtnClient::Config.configurations[env]["product_name"]
133
- version = SgtnClient::Config.configurations[env]["version"].to_s
134
- translation_bundle = SgtnClient::Config.configurations[env]["translation_bundle"]
135
- bundlepath = translation_bundle + "/" + product_name + "/" + version + "/" + component + "/messages_" + locale + ".json"
136
- SgtnClient::FileUtil.read_json(bundlepath)
137
- end
98
+ extend SgtnClient::TranslationLoader::SourceComparer
99
+ extend SgtnClient::TranslationLoader::Cache
138
100
 
139
- def self.load_s(component, locale)
140
- env = SgtnClient::Config.default_environment
141
- product_name = SgtnClient::Config.configurations[env]["product_name"]
142
- vip_server = SgtnClient::Config.configurations[env]["vip_server"]
143
- version = SgtnClient::Config.configurations[env]["version"].to_s
144
- url = vip_server + "/i18n/api/v2/translation/products/" + product_name + "/versions/" + version + "/locales/" + locale + "/components/" + component+ "?checkTranslationStatus=false&machineTranslation=false&pseudo=false"
145
- begin
146
- obj = SgtnClient::Core::Request.get(url)
147
- rescue => exception
148
- SgtnClient.logger.error exception.message
149
- end
150
- if obj != nil
151
- obj = obj["data"]
152
- end
153
- return obj
101
+ load_translations
102
+ @initialized = true
154
103
  end
155
104
 
156
- end
105
+ def load_translations; end
106
+ end
157
107
 
108
+ private_class_method :getTranslation, :get_cs, :load_bundle, :initialized?, :load_translations
109
+ end
158
110
  end
@@ -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
@@ -5,99 +5,30 @@ require 'date'
5
5
 
6
6
  module SgtnClient::Core
7
7
  class Cache
8
- Entry = Struct.new(:expiry, :value)
8
+ Entry = Struct.new(:expiry, :items)
9
9
 
10
10
  def self.initialize(disabled=false, opts={})
11
11
  @@opts = opts
12
- @mutex = Mutex.new
13
- if disabled == false
14
- @@data = Hash.new
15
- SgtnClient.logger.debug "[Cache][initialize]cache is enabled!"
16
- else
17
- @@data = nil
18
- SgtnClient.logger.debug "[Cache][initialize]cache is disabled!"
19
- end
20
- end
21
-
22
- def self.keys
23
- if @@data == nil
24
- return nil
25
- end
26
- SgtnClient.logger.debug "[Cache][keys]get cache keys"
27
- @@data.keys
12
+ SgtnClient.logger.debug "[Cache][initialize] Disable cache? #{disabled}"
13
+ @@data = Hash.new
28
14
  end
29
15
 
30
16
  def self.get(key)
31
- if @@data == nil
32
- return nil, nil
33
- end
34
17
  SgtnClient.logger.debug "[Cache][get]get cache for key: " + key
35
- invalidate(key)
36
- end
37
-
38
- def self.has(key)
39
- if @@data == nil
40
- return nil
41
- end
42
- SgtnClient.logger.debug "[Cache][has]check if the cache has key: #{(@@data.has_key? key)}"
43
- @@data.has_key? key
18
+ return @@data&.dig(key)
44
19
  end
45
20
 
46
- def self.put(key, value, ttl=nil)
47
- @mutex.synchronize do
48
- if @@data == nil || value == nil
49
- return nil
50
- end
51
- ttl ||= @@opts[:ttl]
52
- # hours from new
53
- SgtnClient.logger.debug "[Cache][put]put cache for key '" + key + "' with expired time at'" + (Time.now + ttl*60).to_s
54
- @@data[key] = Entry.new(Time.now + ttl*60, value)
55
- end
56
- end
57
-
58
- def self.delete(key)
59
- @mutex.synchronize do
60
- if @@data == nil
61
- return nil
62
- end
63
- SgtnClient.logger.debug "[Cache][delete]delete cache for key: " + key
64
- @@data.delete key
65
- 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)
66
26
  end
67
27
 
68
28
  def self.clear
69
- @mutex.synchronize do
70
- if @@data == nil
71
- return nil
72
- end
73
- SgtnClient.logger.debug "[Cache][clear]clear cache!"
74
- @@data = Hash.new
75
- end
76
- end
77
-
78
- def self.invalidate(key)
79
- @mutex.synchronize do
80
- if @@data == nil
81
- return nil, nil
82
- end
83
- SgtnClient.logger.debug "[Cache][invalidate]invalidate expired cache......"
84
- now = Time.now
85
- if has(key)
86
- v = @@data[key]
87
- expired = false
88
- SgtnClient.logger.debug "[Cache][invalidate]check cache: key=#{key}, expiredtime=#{v[:expiry]}, now=#{now}, expired=#{(v[:expiry] < now)}"
89
- if v[:expiry] < now
90
- SgtnClient.logger.debug "[Cache][invalidate]before deleting the cache: data=#{@@data}"
91
- @@data.delete(key)
92
- SgtnClient.logger.debug "[Cache][invalidate]after deleting the cache: data=#{@@data}"
93
- expired = true
94
- end
95
- return expired, v[:value]
96
- else
97
- return nil, nil
98
- end
99
- end
29
+ SgtnClient.logger.debug "[Cache][clear]clear cache!"
30
+ @@data = Hash.new
100
31
  end
101
32
  end
102
33
 
103
- end
34
+ 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,48 +1,43 @@
1
1
  # Copyright 2022 VMware, Inc.
2
2
  # SPDX-License-Identifier: EPL-2.0
3
3
 
4
- require 'erb'
5
- require 'yaml'
6
-
7
4
  module SgtnClient
8
-
9
5
  module Core
10
- autoload :Cache, "sgtn-client/core/cache"
6
+ autoload :Cache, 'sgtn-client/core/cache'
11
7
  end
12
-
8
+
13
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
14
+
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?
22
+
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
14
41
 
15
- def self.get_cache(cache_key)
16
- expired, items = SgtnClient::Core::Cache.get(cache_key)
17
- SgtnClient.logger.debug "[CacheUtil]get cache with key #{cache_key}, expired #{expired}"
18
- return expired, items
19
- end
20
-
21
- def self.clear_cache()
22
- SgtnClient::Core::Cache.clear()
23
- SgtnClient.logger.debug "[CacheUtil]clear cache"
24
- end
25
-
26
- def self.write_cache(cache_key, items)
27
- if items.nil?
28
- return nil
29
- end
30
- env = SgtnClient::Config.default_environment
31
- cache_expiry_period = SgtnClient::Config.configurations[env]["cache_expiry_period"]
32
- # expired after 24 hours
33
- if cache_expiry_period == nil
34
- cache_expiry_period = 24*60
35
- end
36
- SgtnClient.logger.debug "[CacheUtil]write cache with key #{cache_key}, cache_expiry_period #{cache_expiry_period}, itmes #{items}"
37
- SgtnClient::Core::Cache.put(cache_key, items, cache_expiry_period)
38
- end
39
-
40
- def self.get_cachekey(component, locale)
41
- env = SgtnClient::Config.default_environment
42
- product_name = SgtnClient::Config.configurations[env]["product_name"]
43
- version = SgtnClient::Config.configurations[env]["version"].to_s
44
- product_name + "_" + version + "_" + component + "_" + locale
45
- end
46
42
  end
47
-
48
43
  end
@@ -1,37 +1,24 @@
1
1
  # Copyright 2022 VMware, Inc.
2
2
  # SPDX-License-Identifier: EPL-2.0
3
3
 
4
- require 'erb'
5
- require 'yaml'
4
+ autoload :YAML, 'yaml'
5
+ autoload :MultiJson, 'multi_json'
6
6
 
7
7
  module SgtnClient
8
8
 
9
9
  class FileUtil
10
-
11
- @mutex = Mutex.new
12
-
13
10
  def self.read_json(bundlepath)
14
11
  SgtnClient.logger.debug "[FileUtil]read json file from: " + bundlepath
15
- @mutex.synchronize do
16
- data_hash = nil
17
- begin
18
- file = File.read(bundlepath)
19
- data_hash = MultiJson.load(file)
20
- rescue => exception
21
- SgtnClient.logger.error exception.message
22
- end
23
- return data_hash
12
+ begin
13
+ return MultiJson.load(File.read(bundlepath))
14
+ rescue => exception
15
+ SgtnClient.logger.error exception.message
24
16
  end
17
+ nil
25
18
  end
26
19
 
27
20
  def self.read_yml(file_name)
28
- SgtnClient.logger.debug "[FileUtil]read yml file from: " + file_name
29
- @mutex.synchronize do
30
- erb = ERB.new(File.read(file_name))
31
- erb.filename = file_name
32
- YAML.load(erb.result)
33
- end
21
+ YAML::load(File.read(file_name))
34
22
  end
35
23
  end
36
-
37
24
  end
@@ -1,46 +1,48 @@
1
1
  # Copyright 2022 VMware, Inc.
2
2
  # SPDX-License-Identifier: EPL-2.0
3
+ require 'set'
3
4
 
4
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
5
14
 
6
- DEFAULT_LOCALES = ['en', 'de', 'es', 'fr', 'ko', 'ja', 'zh-Hans', 'zh-Hant']
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
- }
14
-
15
- class LocaleUtil
16
- def self.get_best_locale(locale)
17
- fallback(process_locale(locale))
18
- end
19
- def self.process_locale(locale=nil)
20
- locale ||= SgtnClient::Config.configurations.default
21
- locale.to_s
22
- end
23
- def self.fallback(locale)
24
- found = SgtnClient::DEFAULT_LOCALES.select {|e| e == locale}
25
- if !found.empty?
26
- return found[0]
27
- end
28
- if SgtnClient::MAP_LOCALES.key?(locale)
29
- return SgtnClient::MAP_LOCALES[locale]
30
- end
31
- parts = locale.split("-")
32
- if parts.size > 1
33
- f = SgtnClient::DEFAULT_LOCALES.select {|e| e == parts[0]}
34
- if !f.empty?
35
- return f[0]
36
- end
37
- end
38
- return locale
39
- end
40
- def self.get_source_locale
41
- env = SgtnClient::Config.default_environment
42
- source_locale = SgtnClient::Config.configurations[env]["default_language"]
43
- source_locale || 'en'
44
- end
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)) )
45
35
  end
36
+
37
+ def self.get_source_locale
38
+ 'en'
39
+ 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
46
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
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.32
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-03-09 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