singleton-client 0.7.4 → 0.7.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (38) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +27 -28
  3. data/lib/sgtn-client/api/source.rb +10 -66
  4. data/lib/sgtn-client/api/t.rb +20 -18
  5. data/lib/sgtn-client/api/translation.rb +82 -116
  6. data/lib/sgtn-client/cldr/core_ext.rb +4 -1
  7. data/lib/sgtn-client/cldr/localized_date.rb +4 -1
  8. data/lib/sgtn-client/cldr/localized_datetime.rb +4 -1
  9. data/lib/sgtn-client/cldr/localized_str.rb +4 -1
  10. data/lib/sgtn-client/cldr/localized_time.rb +4 -1
  11. data/lib/sgtn-client/common/data.rb +30 -0
  12. data/lib/sgtn-client/common/single_operation.rb +34 -0
  13. data/lib/sgtn-client/core/cache.rb +14 -80
  14. data/lib/sgtn-client/core/config.rb +42 -3
  15. data/lib/sgtn-client/core/exceptions.rb +3 -0
  16. data/lib/sgtn-client/core/logging.rb +3 -1
  17. data/lib/sgtn-client/exceptions.rb +6 -0
  18. data/lib/sgtn-client/formatters/plurals/plural_formatter.rb +4 -1
  19. data/lib/sgtn-client/loader/cache.rb +71 -0
  20. data/lib/sgtn-client/loader/chain_loader.rb +49 -0
  21. data/lib/sgtn-client/loader/consts.rb +15 -0
  22. data/lib/sgtn-client/loader/loader_factory.rb +33 -0
  23. data/lib/sgtn-client/loader/local_translation.rb +49 -0
  24. data/lib/sgtn-client/loader/server.rb +94 -0
  25. data/lib/sgtn-client/loader/single_loader.rb +48 -0
  26. data/lib/sgtn-client/loader/source.rb +56 -0
  27. data/lib/sgtn-client/loader/source_comparer.rb +58 -0
  28. data/lib/sgtn-client/sgtn-client.rb +11 -1
  29. data/lib/sgtn-client/util/cache-util.rb +33 -44
  30. data/lib/sgtn-client/util/locale-util.rb +67 -28
  31. data/lib/sgtn-client/util/string-util.rb +12 -0
  32. data/lib/sgtn-client/util/validate-util.rb +4 -7
  33. data/lib/singleton-client.rb +15 -0
  34. data/lib/singleton-ruby.rb +5 -0
  35. data/lib/version.rb +2 -0
  36. metadata +43 -147
  37. data/lib/sgtn-client/core/request.rb +0 -21
  38. data/lib/sgtn-client/util/file-util.rb +0 -34
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 43d840f37ce5f60b23e16623db0b4393f014eaeaafa0ddf91520225a93bd9c57
4
- data.tar.gz: d3c1e045e6c75f7e09cd2790de733a217516afede51dbfede1224cbabcbd3b53
3
+ metadata.gz: f94c0be66f68113fc69f95dbf7d55dac5c21854acc5cf89381e92e0ce0a6abd1
4
+ data.tar.gz: d70dd2bbc7b19af02a70a4de9be14aa39d50a3e043b310074b8fa84fbeb50f2f
5
5
  SHA512:
6
- metadata.gz: 56593be0f8686d669216a849592b9100bb47f52087bf10938d1fae79fb123b9b4ee68baa10e8e627c2ef263e79f2f056aac777e2e5ebc3d8d7f5fbd15b758ce5
7
- data.tar.gz: 5eca696945202e002be5c489ee37153d63c6498e4cc8639f5ea3ad11666ac63e4fffee59572e29fbeb0ff4c7489ff29b06a77cb57e2f9f077cde0663ca5e115b
6
+ metadata.gz: 3be87ccbb4b86a43e75bdc7b6cf2d3e989d640ee99a4140e0a84f372ab9a4bbd43966f6cbd264892435c02f0ddb1c41c07a6a9e4524bb1222e8eb2a0e206c487
7
+ data.tar.gz: adc2e6eca62d579fd134e3cf8b19e49368ecc79541faa6d5195c812482ab5bcc0b2aff4000d836cf007ef0b0afffb3f2c465f954c95d1a1b16378a51b1e31f99
data/README.md CHANGED
@@ -1,54 +1,53 @@
1
- # Singeleton client for Ruby
1
+ # Singleton Client for Ruby
2
2
 
3
3
  ## Prerequisites
4
4
  - Ruby version: 3.0.0 or above
5
5
  - Bundler version: 2.2.3 or above
6
6
 
7
7
  ## Run Unit Test
8
- rake spec:unit
8
+ `rake spec`
9
9
 
10
10
  ## Usage
11
11
 
12
12
  Basic Usage:
13
13
 
14
14
  ```ruby
15
- require 'singleton-ruby'
16
-
17
- include SgtnClient
18
-
19
- SgtnClient.load(file, mode)
20
-
21
- SgtnClient::Source.loadBundles(locale)
22
-
23
- @Result = SgtnClient::Translation.getString(component, key, locale)
15
+ require 'singleton-client'
24
16
 
17
+ Sgtn.load_config(file, env)
18
+ result = Sgtn.translate(key, component, locale)
25
19
  ```
26
20
  ## API Usage
27
21
 
28
22
  ### Get a string's translation
29
- SgtnClient::Translation.getString(component, key, locale)
30
-
31
- ### Get a string's translation and format it with placeholders
32
- SgtnClient::Translation.getString_f(component, key, args, locale)
33
-
34
- ### Get a component's translations
35
- SgtnClient::Translation.getStrings(component, locale)
36
-
23
+ `result = Sgtn.translate(key, component, locale)`
37
24
 
38
- ## API Usage(with request_store)
39
-
40
- Before call below APIs(without locale and component arguments), it requires to set the locale and component in the initial codes.
41
-
42
- ### Get a string's translation
43
- SgtnClient::T.s(key)
25
+ ### Get a string's translation with default value when no translation
26
+ `result = Sgtn.translate(key, component, locale) { 'default value' }`
44
27
 
45
28
  ### Get a string's translation and format it with placeholders
46
- SgtnClient::T.s_f(key, args)
29
+ `result = Sgtn.translate(key, component, locale, **args)`
47
30
 
48
- ### Get a component's translations
49
- SgtnClient::T.c()
31
+ ### Get pluralized translation
32
+ `result = Sgtn.translate(key, component, locale, **args)`
50
33
 
34
+ ### Get translations of a bundle
35
+ `result = Sgtn.get_translations(component, locale)`
51
36
 
37
+ ### Set locale for a request
38
+ `Sgtn.locale = 'en'`
52
39
 
40
+ ### Get locale of the request
41
+ `result = Sgtn.locale`
53
42
 
43
+ ### Get a string's translation with locale set
44
+ ```ruby
45
+ Sgtn.locale = 'en'
46
+ result = Sgtn.translate(key, component)
47
+ ```
54
48
 
49
+ ### Get translations of a bundle with locale set
50
+ ```ruby
51
+ Sgtn.locale = 'en'
52
+ result = Sgtn.get_translations(component)
53
+ ```
@@ -1,71 +1,15 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
4
+ require 'sgtn-client/loader/source'
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
67
- end
68
-
10
+ def self.loadBundles(locale)
11
+ SgtnClient.logger.debug "[Source][loadBundles]locale=#{locale}"
12
+ SgtnClient::Config.configurations.default = locale
13
+ end
69
14
  end
70
-
71
- end
15
+ 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,113 @@
1
- require 'multi_json'
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
2
3
 
3
- 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"
10
- end
11
-
12
- class Translation
4
+ require 'request_store'
13
5
 
14
- def self.getString(component, key, locale)
6
+ module SgtnClient
7
+ module Translation
8
+ module Implementation
9
+ # <b>DEPRECATED:</b> Please use <tt>Sgtn:translate</tt> instead.
10
+ def getString(component, key, locale)
15
11
  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
22
- end
23
- str
12
+ translate(key, component, locale) { nil }
24
13
  end
25
14
 
26
- def self.getString_p(component, key, plural_args, locale)
15
+ # <b>DEPRECATED:</b> Please use <tt>Sgtn:translate</tt> instead.
16
+ def getString_p(component, key, plural_args, locale)
27
17
  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)
38
- end
18
+ translate(key, component, locale, **plural_args) { nil }
39
19
  end
40
20
 
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)
21
+ # <b>DEPRECATED:</b> Please use <tt>Sgtn:translate</tt> instead.
22
+ def getString_f(component, key, args, locale, *_optionals)
23
+ SgtnClient.logger.debug "[Translation][getString_f]component=#{component}, key=#{key}, locale=#{locale}"
24
+ s = translate(key, component, locale) { nil }
25
+ return nil if s.nil?
26
+
27
+ if args.is_a?(Hash)
48
28
  args.each do |source, arg|
49
29
  s.gsub! "{#{source}}", arg
50
30
  end
51
- elsif args.is_a?(Array)
52
- s = sprintf s % args
53
- end
54
- return s
31
+ elsif args.is_a?(Array)
32
+ s = s % args
33
+ end
34
+ s
55
35
  end
56
36
 
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
37
+ # <b>DEPRECATED:</b> Please use <tt>Sgtn:get_translations</tt> instead.
38
+ def getStrings(component, locale)
39
+ get_translations(component, locale)
40
+ end
41
+
42
+ # raise error when translation is not found
43
+ def translate(key, component, locale = nil, **kwargs)
44
+ SgtnClient.logger.debug "[#{method(__callee__).owner}.#{__callee__}] key: #{key}, component: #{component}, locale: #{locale}, args: #{kwargs}"
45
+
46
+ locale = locale.nil? ? self.locale : SgtnClient::LocaleUtil.get_best_locale(locale)
47
+
48
+ result = get_bundle(component, locale)&.fetch(key, nil)
49
+ if result.nil? && !LocaleUtil.is_source_locale(locale)
50
+ locale = LocaleUtil.get_source_locale
51
+ result = get_bundle(component, locale)&.fetch(key, nil)
72
52
  end
73
- return items
74
- end
75
53
 
54
+ if result.nil?
55
+ return key unless block_given?
76
56
 
77
- private
57
+ result = yield
58
+ return if result.nil?
59
+ end
78
60
 
79
- def self.getTranslation(component, key, locale)
80
- items = get_cs(component, locale)
81
- if items.nil? || items["messages"] == nil
82
- nil
61
+ if kwargs.empty?
62
+ result
83
63
  else
84
- items["messages"][key]
64
+ locale = result.locale if result.is_a?(SgtnClient::StringUtil)
65
+ result.localize(locale) % kwargs
85
66
  end
86
67
  end
68
+ alias t translate
87
69
 
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
70
+ def get_translations(component, locale = nil)
71
+ SgtnClient.logger.debug "[#{method(__callee__).owner}.#{__callee__}] component: #{component}, locale: #{locale}"
72
+
73
+ locale = locale.nil? ? self.locale : SgtnClient::LocaleUtil.get_best_locale(locale)
74
+ items = get_bundle(component, locale)
75
+ if items.nil? && !LocaleUtil.is_source_locale(locale)
76
+ items = get_bundle(component, LocaleUtil.get_source_locale)
77
+ locale = LocaleUtil.get_source_locale
103
78
  end
104
79
 
105
- return items
106
- end
80
+ { 'component' => component, 'locale' => locale, 'messages' => items || {} } if items
81
+ end
107
82
 
108
- def self.load(component, locale)
109
- env = SgtnClient::Config.default_environment
110
- mode = SgtnClient::Config.configurations[env]["bundle_mode"]
111
- SgtnClient.logger.debug "[Translation][load]mode=#{mode}"
112
- if mode == 'offline'
113
- return load_o(component, locale)
114
- else
115
- return load_s(component, locale)
116
- end
83
+ def locale
84
+ RequestStore.store[:locale] ||= SgtnClient::LocaleUtil.get_fallback_locale
117
85
  end
118
86
 
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)
87
+ def locale=(value)
88
+ RequestStore.store[:locale] = SgtnClient::LocaleUtil.get_best_locale(value)
126
89
  end
127
90
 
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
91
+ private
92
+
93
+ def get_bundle(component, locale)
94
+ get_bundle!(component, locale)
95
+ rescue StandardError => e
96
+ SgtnClient.logger.error "[#{method(__callee__).owner}.#{__callee__}] failed to get a bundle. component: #{component}, locale: #{locale}"
97
+ SgtnClient.logger.error e
98
+ nil
143
99
  end
144
100
 
145
- end
101
+ def get_bundle!(component, locale)
102
+ id = SgtnClient::Common::BundleID.new(component, locale)
103
+ bundles = SgtnClient::Config.available_bundles
104
+ unless bundles.nil? || bundles.empty? || bundles.include?(id)
105
+ raise SgtnClient::SingletonError, 'bundle is unavailable.'
106
+ end
146
107
 
147
- end
108
+ SgtnClient::Config.loader.get_bundle(component, locale)
109
+ end
110
+ end
111
+ extend Implementation
112
+ end
113
+ 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,5 +1,8 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
1
3
 
2
4
  String.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
5
+ # <b>DEPRECATED:</b> Please use <tt>Sgtn:translate</tt> instead.
3
6
  def to_plural_s(locale, arg)
4
7
  num_str = SgtnClient::Formatters::PluralFormatter.new(locale).num_s(self, arg)
5
8
  if num_str.nil? || num_str.empty?
@@ -8,4 +11,4 @@ String.class_eval <<-LOCALIZE, __FILE__, __LINE__ + 1
8
11
  num_str
9
12
  end
10
13
  end
11
- LOCALIZE
14
+ 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,30 @@
1
+ # Copyright 2022 VMware, Inc.
2
+ # SPDX-License-Identifier: EPL-2.0
3
+
4
+ module SgtnClient
5
+ module Common
6
+ class BundleID
7
+ attr_reader :locale, :component
8
+
9
+ def initialize(component, locale)
10
+ @locale = locale
11
+ @component = component
12
+ @key = [@component, @locale].hash
13
+ end
14
+
15
+ def hash
16
+ @key
17
+ end
18
+
19
+ def ==(other)
20
+ (other.is_a? self.class) && @locale == other.locale && @component == other.component
21
+ end
22
+
23
+ alias eql? ==
24
+
25
+ def to_s
26
+ "locale=#{@locale}, component=#{@component}}"
27
+ end
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,34 @@
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
+ # TODO: whatif returning nil
24
+ @hash[id] = @creator.call(id, obj, *args)
25
+ end
26
+ end
27
+
28
+ def remove_object(id)
29
+ @lock.synchronize do
30
+ @hash.delete(id)
31
+ end
32
+ end
33
+ end
34
+ end