haveapi 0.29.2 → 0.29.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 3de67ba481b9c0e88a56b07403e1979e24558ee8f52f3c1eb9d720faa442a62b
4
- data.tar.gz: 1d3d0d435612eceeba75ec9973082f7eeca6fd8f7c5010197cb324edd606c843
3
+ metadata.gz: 885ac3cc2e4b40ee6595f9beadad79e75f371d607dd0d49d02f67a01cece7d7f
4
+ data.tar.gz: 8c8b186ae1299655f952bedf5cd857042df97b060a0fda7e43ef6b9bc0ec6393
5
5
  SHA512:
6
- metadata.gz: 40fcf28b778528046eab97d60034de89210b41c3e7977f12d622c0b8248bc89c231663eb355b5284693db781a3f25887c719ec6ca76effbfb604a10a914762e2
7
- data.tar.gz: 7cd757b4ff23dfdd3dbe5efd732ceb23c6adb1bc763ed117de84687ee5c23652a7e71332e7f8762b94eca198b5b5cdbd76a2cf2f5698b876b9032343b98e1fab
6
+ metadata.gz: 8b3cd3b9dabb84f88119dde487b150ea6694ab76450d24df1c8f7ff9309b5fcb91638d58f4794db0236de5d8a81c01693c3a5adfc9665200bdb24915599d131e
7
+ data.tar.gz: c738c43d4cc3437124e9af50cd1ae70c84d3f5a91cb93f4c6d1b0966257e011f438f8ecf36639ba0da5044b0b06aa5c8b6072dce4793d4546df424ebdc50a1a9
data/haveapi.gemspec CHANGED
@@ -15,7 +15,7 @@ Gem::Specification.new do |s|
15
15
  s.required_ruby_version = ">= #{File.read('../../.ruby-version').strip}"
16
16
 
17
17
  s.add_dependency 'activesupport', '>= 7.1'
18
- s.add_dependency 'haveapi-client', '~> 0.29.2'
18
+ s.add_dependency 'haveapi-client', '~> 0.29.3'
19
19
  s.add_dependency 'i18n', '>= 1.6', '< 2'
20
20
  s.add_dependency 'json'
21
21
  s.add_dependency 'mail'
@@ -38,8 +38,7 @@ module HaveAPI::Authentication
38
38
 
39
39
  def describe
40
40
  {
41
- description: 'Authentication using HTTP basic. Username and password is passed ' \
42
- 'via HTTP header. Its use is forbidden from web browsers.'
41
+ description: HaveAPI.message('haveapi.authentication.basic.description')
43
42
  }
44
43
  end
45
44
 
@@ -54,7 +54,7 @@ module HaveAPI::Authentication
54
54
  return ret unless @instances[context.version]
55
55
 
56
56
  @instances[context.version].each do |provider|
57
- ret[provider.name] = provider.describe
57
+ ret[provider.name] = HaveAPI.localize(provider.describe)
58
58
 
59
59
  next unless provider.resource_module
60
60
 
@@ -150,24 +150,8 @@ module HaveAPI::Authentication
150
150
  end
151
151
 
152
152
  def describe
153
- desc = <<-END
154
- OAuth2 authorization provider. While OAuth2 support in HaveAPI clients
155
- is limited, it is possible to use your API as an authentication source
156
- and to use OAuth2 tokens to access the API.
157
-
158
- HaveAPI partially implements RFC 6749: authorization response type "code"
159
- and token grant types "authorization_code" and "refresh_token". Other
160
- response and grant types are not supported at this time.
161
-
162
- The access token can be passed as bearer token according to RFC 6750,
163
- or using a custom HTTP header when the Authorization header is not
164
- practical.
165
-
166
- The access and refresh tokens can be revoked as per RFC 7009.
167
- END
168
-
169
153
  {
170
- description: desc,
154
+ description: HaveAPI.message('haveapi.authentication.oauth2.description'),
171
155
  http_header: config.http_header,
172
156
  authorize_url: @authorize_url,
173
157
  authorize_path: @authorize_path,
@@ -185,7 +185,7 @@ module HaveAPI::Authentication
185
185
  {
186
186
  http_header: config.class.http_header,
187
187
  query_parameter: config.class.query_parameter,
188
- description: 'The client authenticates with credentials, usually username and password, and gets a token. From this point, the credentials can be forgotten and the token is used instead. Tokens can have different lifetimes, can be renewed and revoked. The token is passed either via HTTP header or query parameter.'
188
+ description: HaveAPI.message('haveapi.authentication.token.description')
189
189
  }
190
190
  end
191
191
 
@@ -203,12 +203,16 @@ module HaveAPI::Authentication
203
203
  provider = self
204
204
 
205
205
  HaveAPI::Resource.define_resource(:Token) do
206
+ desc HaveAPI.message('haveapi.authentication.token.resource.description')
207
+
206
208
  define_singleton_method(:token_instance) { provider }
207
209
 
208
210
  auth false
209
211
  version :all
210
212
 
211
213
  define_action(:Request) do
214
+ desc HaveAPI.message('haveapi.authentication.token.actions.request.description')
215
+
212
216
  route ''
213
217
  http_method :post
214
218
 
@@ -275,6 +279,8 @@ module HaveAPI::Authentication
275
279
  end
276
280
 
277
281
  define_action(:Revoke) do
282
+ desc HaveAPI.message('haveapi.authentication.token.actions.revoke.description')
283
+
278
284
  http_method :post
279
285
  auth true
280
286
 
@@ -318,6 +324,8 @@ module HaveAPI::Authentication
318
324
  end
319
325
 
320
326
  define_action(:Renew) do
327
+ desc HaveAPI.message('haveapi.authentication.token.actions.renew.description')
328
+
321
329
  http_method :post
322
330
  auth true
323
331
 
@@ -5,33 +5,57 @@
5
5
  cs:
6
6
  haveapi:
7
7
  action_state:
8
- cancellation_failed: zrušení selhalo
9
- not_found: stav akce nebyl nalezen
10
- timeout_max: timeout může být nejvýše %{max}
8
+ cancellation_failed: Zrušení akce se nezdařilo
9
+ not_found: Stav akce nebyl nalezen
10
+ timeout_max: Časový limit může být nejvýše %{max}
11
11
  authentication:
12
- failed: přihlášení selhalo
13
- invalid_credentials: neplatné přihlašovací údaje
14
- multiple_oauth2_tokens: Bylo poskytnuto více OAuth2 tokenů
15
- multiple_tokens: Bylo poskytnuto více ověřovacích tokenů
16
- renew_failed: obnovení selhalo
17
- required: Akce vyžaduje přihlášení uživatele
18
- revoke_failed: zrušení selhalo
19
- token_required: Akce vyžaduje přihlášení uživatele tokenem
12
+ basic:
13
+ description: |-
14
+ Autentizace pomocí HTTP Basic. Uživatelské jméno a heslo se předávají v HTTP hlavičce.
15
+ Tato metoda se nesmí používat z webových prohlížečů.
16
+ failed: Přihlášení se nezdařilo
17
+ invalid_credentials: Neplatné přihlašovací údaje
18
+ multiple_oauth2_tokens: Bylo zadáno více OAuth2 tokenů
19
+ multiple_tokens: Bylo zadáno více autentizačních tokenů
20
+ oauth2:
21
+ description: |-
22
+ OAuth2 autorizační provider.
23
+ Podpora OAuth2 v klientech HaveAPI je omezená, ale API lze použít jako zdroj autentizace a k přístupu k API lze používat OAuth2 tokeny. HaveAPI částečně implementuje RFC 6749: autorizační response type "code" a token grant types "authorization_code" a "refresh_token". Ostatní response a grant types momentálně nejsou podporovány. Přístupový token lze předat jako bearer token podle RFC 6750 nebo vlastní HTTP hlavičkou, pokud není praktické použít hlavičku Authorization.
24
+ Přístupové a refresh tokeny lze zneplatnit podle RFC 7009.
25
+ renew_failed: Obnovení tokenu se nezdařilo
26
+ required: Tato akce vyžaduje přihlášení
27
+ revoke_failed: Zneplatnění tokenu se nezdařilo
28
+ token:
29
+ actions:
30
+ renew:
31
+ description: Obnovit aktuální autentizační token
32
+ request:
33
+ description: Vyžádat autentizační token
34
+ revoke:
35
+ description: Zneplatnit aktuální autentizační token
36
+ description: Klient se autentizuje přihlašovacími údaji, obvykle uživatelským
37
+ jménem a heslem, a získá token. Od té chvíle už přihlašovací údaje nepotřebuje
38
+ a používá místo nich token. Tokeny mohou mít různou dobu platnosti a lze
39
+ je obnovovat nebo zneplatňovat. Token se předává buď v HTTP hlavičce, nebo
40
+ jako parametr dotazu.
41
+ resource:
42
+ description: Spravovat autentizační tokeny
43
+ token_required: Tato akce vyžaduje autentizaci tokenem
20
44
  authorization:
21
45
  insufficient_permissions: Přístup odepřen. Nedostatečná oprávnění.
22
46
  errors:
23
47
  action_not_found: Akce nebyla nalezena
24
- bad_accept_header: Chybná hlavička Accept
25
- bad_json_syntax: Chybná syntaxe JSON
26
- json_body_object: Tělo JSON musí být objekt
48
+ bad_accept_header: Neplatná hlavička Accept
49
+ bad_json_syntax: Neplatná syntaxe JSON
50
+ json_body_object: Tělo JSON požadavku musí být objekt
27
51
  server_error: Došlo k chybě serveru
28
- unsupported_content_type: Nepodporovaný Content-Type
52
+ unsupported_content_type: Nepodporovaná hlavička Content-Type
29
53
  pagination:
30
- limit_max: limit může být nejvýše %{max}
54
+ limit_max: Limit může být nejvýše %{max}
31
55
  parameters:
32
56
  action_state:
33
57
  can_cancel:
34
- description: Je-li true, spuštění této akce lze zrušit
58
+ description: Je-li hodnota true, lze běh této akce zrušit
35
59
  label: Lze zrušit
36
60
  created_at:
37
61
  label: Vytvořeno
@@ -43,98 +67,111 @@ cs:
43
67
  label: Popisek
44
68
  poll:
45
69
  current:
46
- description: průběh, se kterým se porovnává při nastaveném update_in
70
+ description: Aktuální průběh pro porovnání, je-li nastaveno update_in
47
71
  status:
48
- description: stav, se kterým se porovnává při nastaveném update_in
72
+ description: Stav pro porovnání, je-li nastaveno update_in
49
73
  timeout:
50
- description: v sekundách
74
+ description: Časový limit v sekundách
51
75
  label: Časový limit
52
76
  total:
53
- description: průběh, se kterým se porovnává při nastaveném update_in
77
+ description: Celkový průběh pro porovnání, je-li nastaveno update_in
54
78
  update_in:
55
- description: počet sekund, po kterém se stav vrátí, pokud se průběh změnil
56
- label: Průběh
79
+ description: Vrátit stav dříve, pokud se změní status, current nebo total;
80
+ hodnota se předává implementacím pollingu v API
81
+ label: Čekat na změnu
57
82
  status:
58
- description: Určuje, zda akce probíhá nebo selhává
83
+ description: Určuje, zda akce probíhá úspěšně nebo selhala
59
84
  label: Stav
60
85
  total:
61
- description: Akce je dokončena, když se aktuální průběh rovná celkovému
86
+ description: Akce je dokončena, když aktuální průběh dosáhne celkového
62
87
  label: Celkem
63
88
  unit:
64
- description: Jednotka aktuálního a celkového průběhu
89
+ description: Jednotka hodnot current a total
65
90
  label: Jednotka
66
91
  updated_at:
67
- description: Kdy byl průběh naposledy aktualizován
92
+ description: Čas poslední aktualizace průběhu
68
93
  label: Aktualizováno
69
94
  action_state_id:
70
- description: ID objektu ActionState pro dotazování stavu. Pokud je null, akce
71
- není pro aktuální volání blokující.
95
+ description: |-
96
+ ID objektu ActionState pro dotazování na stav.
97
+ Pokud je hodnota null, akce v aktuálním volání neblokuje.
72
98
  label: ID stavu akce
73
99
  active_record:
74
100
  includes:
75
- description: |-
76
- Seznam názvů asociovaných prostředků oddělených čárkou.
77
- Vnořené asociace se zapisují pomocí '__' mezi názvy prostředků.
78
- Například 'user,node' přeloží tyto dvě asociace.
79
- Pro přeložení dalších asociací uzlu použijte např. 'user,node__location',
80
- pro ještě hlubší úroveň např. 'user,node__location__environment'.
101
+ description: Seznam názvů asociovaných zdrojů oddělených čárkou. Vnořené
102
+ asociace se zapisují pomocí '__' mezi názvy zdrojů. Například 'user,node'
103
+ načte tyto dvě asociace. Pro načtení dalších asociací zdroje node použijte
104
+ např. 'user,node__location'; pro ještě hlubší úroveň např. 'user,node__location__environment'.
81
105
  label: Zahrnuté asociace
82
106
  path_params:
83
- description: Pole parametrů potřebných k přeložení URL na tento objekt
107
+ description: Pole parametrů potřebných k sestavení URL k tomuto objektu
84
108
  label: Parametry URL
85
109
  resolved:
86
- description: True, pokud je asociace přeložena
87
- label: Přeloženo
110
+ description: True, pokud je asociace načtena
111
+ label: Načteno
88
112
  authentication:
89
113
  token:
90
114
  interval:
91
- description: Jak dlouho bude požadovaný token platný, v sekundách.
115
+ description: Doba platnosti požadovaného tokenu v sekundách.
92
116
  label: Interval
93
117
  lifetime:
94
118
  description: |-
95
119
  fixed - token má pevnou dobu platnosti a nelze ho obnovit
96
- renewable_manual - token lze obnovit, ale musí se obnovit ručně akcí renew
97
- renewable_auto - token se při každém použití automaticky obnoví na now+interval
98
- permanent - token bude platný navždy, dokud nebude smazán
120
+ renewable_manual - platnost tokenu lze prodloužit, ale pouze ručně akcí renew
121
+ renewable_auto - platnost tokenu se při každém použití automaticky prodlouží na now + interval
122
+ permanent - token je platný trvale, dokud není smazán
99
123
  label: Životnost
100
124
  password:
101
125
  label: Heslo
102
126
  scope:
103
- label: Rozsah
127
+ label: Scope
104
128
  user:
105
129
  label: Uživatel
106
130
  default:
107
131
  count:
108
- label: Vrátit počet všech položek
132
+ label: Vrátit celkový počet položek
109
133
  total_count:
110
- label: Celkový počet všech položek
134
+ label: Celkový počet položek
111
135
  metadata:
112
136
  'no':
113
- label: Zakázat metadata
137
+ label: Vypnout metadata
114
138
  paginable:
115
139
  from_id:
116
- description: Vypsat objekty s větším/menším ID
140
+ description: Vypsat objekty s ID větším/menším než zadaná hodnota
117
141
  label: Od ID
118
142
  limit:
119
143
  description: Počet objektů k načtení
120
144
  label: Limit
145
+ resources:
146
+ action_state:
147
+ actions:
148
+ cancel:
149
+ description: Zrušit čekající akci
150
+ index:
151
+ description: Vypsat stavy čekajících akcí
152
+ poll:
153
+ description: Vrátit stav po dokončení akce, změně průběhu nebo vypršení
154
+ časového limitu
155
+ show:
156
+ description: Zobrazit stav čekající akce
157
+ description: Procházet stavy blokujících akcí
121
158
  types:
122
- invalid_boolean: neplatná pravdivostní hodnota %{value}
123
- invalid_datetime: není ve formátu ISO 8601 '%{value}'
124
- invalid_float: neplatné desetinné číslo %{value}
125
- invalid_integer: neplatné celé číslo %{value}
126
- invalid_string: neplatný řetězec %{value}
159
+ invalid_boolean: 'není platná pravdivostní hodnota: %{value}'
160
+ invalid_datetime: 'není ve formátu ISO 8601: ''%{value}'''
161
+ invalid_float: 'není platné desetinné číslo: %{value}'
162
+ invalid_integer: 'není platné celé číslo: %{value}'
163
+ invalid_string: 'není platný řetězec: %{value}'
127
164
  validation:
128
165
  cannot_be_null: nesmí být null
129
166
  includes_only_strings: includes musí obsahovat jen řetězce
130
167
  includes_string_or_array: includes musí být řetězec nebo pole
131
- input_parameters_not_valid: vstupní parametry nejsou platné
132
- invalid_id: neplatné ID %{value}
168
+ input_parameters_not_valid: vstupní parametry jsou neplatné
169
+ invalid_id: 'není platné ID: %{value}'
133
170
  invalid_input_layout: neplatná struktura vstupu
134
171
  invalid_path_parameter_encoding: neplatné kódování parametru cesty
135
172
  invalid_string_encoding: neplatné kódování řetězce
136
- required_parameter_missing: povinný parametr chybí
137
- resource_not_found: prostředek nebyl nalezen
173
+ required_parameter_missing: chybí povinný parametr
174
+ resource_not_found: zdroj nebyl nalezen
138
175
  validators:
139
176
  acceptance:
140
177
  accepted: musí být %{value}
@@ -149,19 +186,19 @@ cs:
149
186
  included: "%{value} nelze použít"
150
187
  length:
151
188
  equals: délka musí být %{equals}
152
- max: délka může být nejvýše %{max}
189
+ max: délka musí být nejvýše %{max}
153
190
  min: délka musí být alespoň %{min}
154
- range: délka musí být v rozsahu <%{min}, %{max}>
191
+ range: délka musí být v rozsahu %{min}–%{max}
155
192
  numericality:
156
193
  composite: "%{requirements}"
157
- even: sudé číslo
194
+ even: musí být sudé číslo
158
195
  max: musí být nejvýše %{max}
159
196
  min: musí být alespoň %{min}
160
197
  mod: zbytek po dělení %{mod} musí být nula
161
198
  number: musí být číslo
162
- odd: liché číslo
163
- range: musí být v rozsahu <%{min}, %{max}>
164
- step: v krocích po %{step}
199
+ odd: musí být liché číslo
200
+ range: musí být v rozsahu %{min}–%{max}
201
+ step: musí být v krocích po %{step}
165
202
  presence:
166
- non_empty: musí být vyplněno a neprázdné
203
+ non_empty: musí být vyplněno a nesmí být prázdné
167
204
  present: musí být vyplněno
@@ -5,33 +5,57 @@
5
5
  en:
6
6
  haveapi:
7
7
  action_state:
8
- cancellation_failed: cancellation failed
9
- not_found: action state not found
10
- timeout_max: timeout has to be maximally %{max}
8
+ cancellation_failed: Action cancellation failed
9
+ not_found: Action state not found
10
+ timeout_max: timeout must be at most %{max}
11
11
  authentication:
12
- failed: authentication failed
13
- invalid_credentials: invalid authentication credentials
14
- multiple_oauth2_tokens: Multiple OAuth2 tokens provided
15
- multiple_tokens: Multiple authentication tokens provided
16
- renew_failed: renew failed
17
- required: Action requires user to authenticate
18
- revoke_failed: revoke failed
19
- token_required: Action requires user to authenticate with a token
12
+ basic:
13
+ description: |-
14
+ Authentication using HTTP Basic. The username and password are passed in an HTTP header.
15
+ This method must not be used from web browsers.
16
+ failed: Authentication failed
17
+ invalid_credentials: Invalid authentication credentials
18
+ multiple_oauth2_tokens: Multiple OAuth2 tokens were provided
19
+ multiple_tokens: Multiple authentication tokens were provided
20
+ oauth2:
21
+ description: |-
22
+ OAuth2 authorization provider.
23
+ HaveAPI clients have limited OAuth2 support, but the API can be used as an authentication source and OAuth2 tokens can be used to access it. HaveAPI partially implements RFC 6749: authorization response type "code" and token grant types "authorization_code" and "refresh_token". Other response and grant types are not supported at this time. The access token can be passed as a bearer token according to RFC 6750, or using a custom HTTP header when the Authorization header is not practical.
24
+ Access and refresh tokens can be revoked according to RFC 7009.
25
+ renew_failed: Token renewal failed
26
+ required: This action requires authentication
27
+ revoke_failed: Token revocation failed
28
+ token:
29
+ actions:
30
+ renew:
31
+ description: Renew the current authentication token
32
+ request:
33
+ description: Request an authentication token
34
+ revoke:
35
+ description: Revoke the current authentication token
36
+ description: The client authenticates with credentials, usually a username
37
+ and password, and receives a token. From that point on, the credentials
38
+ can be forgotten and the token is used instead. Tokens can have different
39
+ lifetimes and can be renewed or revoked. The token is passed either in an
40
+ HTTP header or as a query parameter.
41
+ resource:
42
+ description: Manage authentication tokens
43
+ token_required: This action requires token authentication
20
44
  authorization:
21
45
  insufficient_permissions: Access denied. Insufficient permissions.
22
46
  errors:
23
47
  action_not_found: Action not found
24
- bad_accept_header: Bad Accept header
25
- bad_json_syntax: Bad JSON syntax
26
- json_body_object: JSON body must be an object
27
- server_error: Server error occurred
28
- unsupported_content_type: Unsupported Content-Type
48
+ bad_accept_header: Invalid Accept header
49
+ bad_json_syntax: Invalid JSON syntax
50
+ json_body_object: The JSON request body must be an object
51
+ server_error: A server error occurred
52
+ unsupported_content_type: Unsupported Content-Type header
29
53
  pagination:
30
- limit_max: limit has to be maximally %{max}
54
+ limit_max: limit must be at most %{max}
31
55
  parameters:
32
56
  action_state:
33
57
  can_cancel:
34
- description: When true, execution of this action can be cancelled
58
+ description: When true, this action can be cancelled
35
59
  label: Can cancel
36
60
  created_at:
37
61
  label: Created at
@@ -43,60 +67,59 @@ en:
43
67
  label: Label
44
68
  poll:
45
69
  current:
46
- description: progress to check with if update_in is set
70
+ description: Current progress value to compare when update_in is set
47
71
  status:
48
- description: status to check with if update_in is set
72
+ description: Status value to compare when update_in is set
49
73
  timeout:
50
- description: in seconds
74
+ description: Timeout in seconds
51
75
  label: Timeout
52
76
  total:
53
- description: progress to check with if update_in is set
77
+ description: Total progress value to compare when update_in is set
54
78
  update_in:
55
- description: number of seconds after which the state is returned if the
56
- progress has changed
57
- label: Progress
79
+ description: Return early when status, current, or total changes; the
80
+ value is passed to API-specific polling implementations
81
+ label: Update in
58
82
  status:
59
- description: Determines whether the action is proceeding or failing
83
+ description: Whether the action is proceeding successfully or has failed
60
84
  label: Status
61
85
  total:
62
- description: The action is finished when current equals to total
86
+ description: The action is finished when current reaches total
63
87
  label: Total
64
88
  unit:
65
89
  description: Unit of current and total
66
90
  label: Unit
67
91
  updated_at:
68
- description: When was the progress last updated
92
+ description: When the progress was last updated
69
93
  label: Updated at
70
94
  action_state_id:
71
- description: ID of ActionState object for state querying. When null, the action
72
- is not blocking for the current invocation.
95
+ description: |-
96
+ ID of the ActionState object for state polling.
97
+ When null, the action is not blocking for the current invocation.
73
98
  label: Action state ID
74
99
  active_record:
75
100
  includes:
76
- description: |-
77
- A list of names of associated resources separated by a comma.
78
- Nested associations are declared with '__' between resource names.
79
- For example, 'user,node' will resolve the two associations.
80
- To resolve further associations of node, use e.g. 'user,node__location',
81
- to go even deeper, use e.g. 'user,node__location__environment'.
101
+ description: A comma-separated list of associated resource names. Nested
102
+ associations are declared with '__' between resource names. For example,
103
+ 'user,node' includes these two associations. To include further associations
104
+ of node, use e.g. 'user,node__location'; to go even deeper, use e.g. 'user,node__location__environment'.
82
105
  label: Included associations
83
106
  path_params:
84
- description: An array of parameters needed to resolve URL to this object
107
+ description: An array of parameters needed to build the URL for this object
85
108
  label: URL parameters
86
109
  resolved:
87
- description: True if the association is resolved
110
+ description: True if the association has been loaded
88
111
  label: Resolved
89
112
  authentication:
90
113
  token:
91
114
  interval:
92
- description: How long will requested token be valid, in seconds.
115
+ description: How long the requested token will be valid, in seconds.
93
116
  label: Interval
94
117
  lifetime:
95
118
  description: |-
96
- fixed - the token has a fixed validity period, it cannot be renewed
97
- renewable_manual - the token can be renewed, but it must be done manually via renew action
98
- renewable_auto - the token is renewed automatically to now+interval every time it is used
99
- permanent - the token will be valid forever, unless deleted
119
+ fixed - the token has a fixed validity period and cannot be renewed
120
+ renewable_manual - the token can be renewed, but only manually using the renew action
121
+ renewable_auto - the token is renewed automatically to now + interval whenever it is used
122
+ permanent - the token is valid forever unless deleted
100
123
  label: Lifetime
101
124
  password:
102
125
  label: Password
@@ -106,39 +129,52 @@ en:
106
129
  label: User
107
130
  default:
108
131
  count:
109
- label: Return the count of all items
132
+ label: Return total count
110
133
  total_count:
111
- label: Total count of all items
134
+ label: Total item count
112
135
  metadata:
113
136
  'no':
114
137
  label: Disable metadata
115
138
  paginable:
116
139
  from_id:
117
- description: List objects with greater/lesser ID
140
+ description: List objects with IDs greater or lower than this value
118
141
  label: From ID
119
142
  limit:
120
143
  description: Number of objects to retrieve
121
144
  label: Limit
145
+ resources:
146
+ action_state:
147
+ actions:
148
+ cancel:
149
+ description: Cancel a pending action
150
+ index:
151
+ description: List pending action states
152
+ poll:
153
+ description: Return when the action is completed, its progress changes,
154
+ or a timeout occurs
155
+ show:
156
+ description: Show the state of a pending action
157
+ description: Browse states of blocking actions
122
158
  types:
123
- invalid_boolean: not a valid boolean %{value}
124
- invalid_datetime: not in ISO 8601 format '%{value}'
125
- invalid_float: not a valid float %{value}
126
- invalid_integer: not a valid integer %{value}
127
- invalid_string: not a valid string %{value}
159
+ invalid_boolean: 'not a valid boolean: %{value}'
160
+ invalid_datetime: 'not in ISO 8601 format: ''%{value}'''
161
+ invalid_float: 'not a valid float: %{value}'
162
+ invalid_integer: 'not a valid integer: %{value}'
163
+ invalid_string: 'not a valid string: %{value}'
128
164
  validation:
129
165
  cannot_be_null: cannot be null
130
166
  includes_only_strings: includes must contain only strings
131
167
  includes_string_or_array: includes must be a string or array
132
- input_parameters_not_valid: input parameters not valid
133
- invalid_id: not a valid id %{value}
168
+ input_parameters_not_valid: input parameters are not valid
169
+ invalid_id: 'not a valid ID: %{value}'
134
170
  invalid_input_layout: invalid input layout
135
171
  invalid_path_parameter_encoding: invalid path parameter encoding
136
172
  invalid_string_encoding: invalid string encoding
137
- required_parameter_missing: required parameter missing
173
+ required_parameter_missing: required parameter is missing
138
174
  resource_not_found: resource not found
139
175
  validators:
140
176
  acceptance:
141
- accepted: has to be %{value}
177
+ accepted: must be %{value}
142
178
  confirmation:
143
179
  different: must be different from %{parameter}
144
180
  same: must be the same as %{parameter}
@@ -149,20 +185,20 @@ en:
149
185
  inclusion:
150
186
  included: "%{value} cannot be used"
151
187
  length:
152
- equals: length has to be %{equals}
153
- max: length has to be maximally %{max}
154
- min: length has to be minimally %{min}
155
- range: length has to be in range <%{min}, %{max}>
188
+ equals: length must be %{equals}
189
+ max: length must be at most %{max}
190
+ min: length must be at least %{min}
191
+ range: length must be between %{min} and %{max}
156
192
  numericality:
157
193
  composite: "%{requirements}"
158
- even: even
159
- max: has to be maximally %{max}
160
- min: has to be minimally %{min}
161
- mod: mod %{mod} must equal zero
162
- number: has to be a number
163
- odd: odd
164
- range: has to be in range <%{min}, %{max}>
165
- step: in steps of %{step}
194
+ even: must be even
195
+ max: must be at most %{max}
196
+ min: must be at least %{min}
197
+ mod: remainder after division by %{mod} must be zero
198
+ number: must be a number
199
+ odd: must be odd
200
+ range: must be between %{min} and %{max}
201
+ step: must be in steps of %{step}
166
202
  presence:
167
203
  non_empty: must be present and non-empty
168
204
  present: must be present
@@ -2,7 +2,7 @@ require 'haveapi/resource'
2
2
 
3
3
  module HaveAPI::Resources
4
4
  class ActionState < HaveAPI::Resource
5
- desc 'Browse states of blocking actions'
5
+ desc HaveAPI.message('haveapi.resources.action_state.description')
6
6
  auth false
7
7
  version :all
8
8
 
@@ -54,7 +54,7 @@ module HaveAPI::Resources
54
54
  class Index < HaveAPI::Actions::Default::Index
55
55
  include Mixin
56
56
 
57
- desc 'List states of pending actions'
57
+ desc HaveAPI.message('haveapi.resources.action_state.actions.index.description')
58
58
 
59
59
  input(:hash) do
60
60
  string :order, choices: %w[newest oldest], default: 'newest', fill: true
@@ -85,7 +85,7 @@ module HaveAPI::Resources
85
85
 
86
86
  MAX_TIMEOUT = 30
87
87
 
88
- desc 'Returns when the action is completed or timeout occurs'
88
+ desc HaveAPI.message('haveapi.resources.action_state.actions.poll.description')
89
89
  http_method :get
90
90
  route '{%{resource}_id}/poll'
91
91
 
@@ -157,7 +157,7 @@ module HaveAPI::Resources
157
157
  class Show < HaveAPI::Actions::Default::Show
158
158
  include Mixin
159
159
 
160
- desc 'Show state of a pending action'
160
+ desc HaveAPI.message('haveapi.resources.action_state.actions.show.description')
161
161
 
162
162
  output(:hash) do
163
163
  use :all
@@ -178,6 +178,8 @@ module HaveAPI::Resources
178
178
  end
179
179
 
180
180
  class Cancel < HaveAPI::Action
181
+ desc HaveAPI.message('haveapi.resources.action_state.actions.cancel.description')
182
+
181
183
  http_method :post
182
184
  route '{%{resource}_id}/cancel'
183
185
  blocking true
@@ -1,4 +1,4 @@
1
1
  module HaveAPI
2
2
  PROTOCOL_VERSION = '2.0'.freeze
3
- VERSION = '0.29.2'.freeze
3
+ VERSION = '0.29.3'.freeze
4
4
  end
@@ -638,7 +638,7 @@ describe HaveAPI::Action do
638
638
 
639
639
  expect(last_response.status).to eq(200)
640
640
  expect(api_response).not_to be_ok
641
- expect(api_response.errors[:confirmed]).to include('required parameter missing')
641
+ expect(api_response.errors[:confirmed]).to include('required parameter is missing')
642
642
 
643
643
  call_api([:Test], :batch, { tests: [{ label: 'one' }], _meta: { confirmed: 'maybe' } })
644
644
 
@@ -33,7 +33,7 @@ describe HaveAPI::Action do
33
33
 
34
34
  expect(last_response.status).to eq(200)
35
35
  expect(api_response).not_to be_ok
36
- expect(api_response.errors[:name]).to include('required parameter missing')
36
+ expect(api_response.errors[:name]).to include('required parameter is missing')
37
37
  end
38
38
  end
39
39
 
@@ -69,7 +69,7 @@ describe HaveAPI::Action do
69
69
 
70
70
  expect(last_response.status).to eq(400)
71
71
  expect(api_response).not_to be_ok
72
- expect(api_response.errors[:name]).to include('required parameter missing')
72
+ expect(api_response.errors[:name]).to include('required parameter is missing')
73
73
  end
74
74
  end
75
75
  end
@@ -184,7 +184,7 @@ describe HaveAPI::Resources::ActionState do
184
184
  get_action '/v1/action_states/999'
185
185
 
186
186
  expect(api_response).not_to be_ok
187
- expect(api_response.message).to eq('action state not found')
187
+ expect(api_response.message).to eq('Action state not found')
188
188
  end
189
189
 
190
190
  it 'poll returns immediately if finished' do
@@ -227,7 +227,7 @@ describe HaveAPI::Resources::ActionState do
227
227
 
228
228
  expect(last_response.status).to eq(200)
229
229
  expect(api_response).not_to be_ok
230
- expect(api_response.errors[:timeout].first).to include('range <0, 30>')
230
+ expect(api_response.errors[:timeout].first).to include('between 0 and 30')
231
231
  end
232
232
 
233
233
  it 'poll returns immediately when update_in check mismatches' do
@@ -274,7 +274,7 @@ describe HaveAPI::Resources::ActionState do
274
274
  get_action '/v1/action_states/999/poll', action_state: { timeout: 0 }
275
275
 
276
276
  expect(api_response).not_to be_ok
277
- expect(api_response.message).to eq('action state not found')
277
+ expect(api_response.message).to eq('Action state not found')
278
278
  end
279
279
 
280
280
  it 'cancel returns ok for true' do
@@ -303,7 +303,7 @@ describe HaveAPI::Resources::ActionState do
303
303
  call_api(:post, '/v1/action_states/1/cancel', {})
304
304
 
305
305
  expect(api_response).not_to be_ok
306
- expect(api_response.message).to eq('cancellation failed')
306
+ expect(api_response.message).to eq('Action cancellation failed')
307
307
  end
308
308
 
309
309
  it 'cancel returns error for NotImplementedError' do
@@ -73,7 +73,7 @@ describe HaveAPI::Authentication::Basic::Provider do
73
73
  expect(last_response.headers['www-authenticate']).to include('Basic realm=')
74
74
 
75
75
  expect(api_response).to be_failed
76
- expect(api_response.message).to include('authenticate')
76
+ expect(api_response.message).to eq('This action requires authentication')
77
77
  expect(seen_users.last).to be_nil
78
78
  end
79
79
 
@@ -123,7 +123,7 @@ describe HaveAPI::Authentication::Basic::Provider do
123
123
  expect(last_response.status).to eq(401)
124
124
  expect(last_response.headers['www-authenticate']).to include('Basic realm=')
125
125
  expect(api_response).to be_failed
126
- expect(api_response.message).to include('authenticate')
126
+ expect(api_response.message).to eq('This action requires authentication')
127
127
  end
128
128
 
129
129
  it 'returns an authentication error envelope from _logout' do
@@ -132,6 +132,6 @@ describe HaveAPI::Authentication::Basic::Provider do
132
132
  expect(last_response.status).to eq(401)
133
133
  expect(last_response.headers['www-authenticate']).to include('Basic realm=')
134
134
  expect(api_response).to be_failed
135
- expect(api_response.message).to include('authenticate')
135
+ expect(api_response.message).to eq('This action requires authentication')
136
136
  end
137
137
  end
@@ -225,7 +225,7 @@ describe HaveAPI::Authentication::OAuth2 do
225
225
 
226
226
  expect(last_response.status).to eq(400)
227
227
  expect(api_response).to be_failed
228
- expect(api_response.message).to eq('Bylo poskytnuto více OAuth2 tokenů')
228
+ expect(api_response.message).to eq('Bylo zadáno více OAuth2 tokenů')
229
229
  end
230
230
 
231
231
  it 'ignores structured access_token query values before backend lookup' do
@@ -248,6 +248,7 @@ describe HaveAPI::Authentication::OAuth2 do
248
248
  end
249
249
 
250
250
  it 'exposes oauth2 provider in version description' do
251
+ header 'Accept-Language', 'cs'
251
252
  call_api(:options, '/v1/')
252
253
 
253
254
  expect(last_response.status).to eq(200)
@@ -257,6 +258,7 @@ describe HaveAPI::Authentication::OAuth2 do
257
258
  expect(auth).to have_key(:oauth2)
258
259
 
259
260
  desc = auth[:oauth2]
261
+ expect(desc[:description]).to start_with('OAuth2 autorizační provider')
260
262
  expect(desc).to have_key(:http_header)
261
263
  expect(desc[:http_header]).to eq('X-HaveAPI-OAuth2-Token')
262
264
 
@@ -290,6 +290,7 @@ describe HaveAPI::Authentication::Token do
290
290
  end
291
291
 
292
292
  it 'exposes token provider in version description' do
293
+ header 'Accept-Language', 'cs'
293
294
  call_api(:options, '/v1/')
294
295
 
295
296
  expect(last_response.status).to eq(200)
@@ -297,11 +298,18 @@ describe HaveAPI::Authentication::Token do
297
298
 
298
299
  auth = api_response[:authentication]
299
300
  expect(auth).to have_key(:token)
301
+ expect(auth[:token][:description]).to start_with('Klient se autentizuje')
300
302
  expect(auth[:token][:http_header]).to eq(AuthSpecToken::Config.http_header)
301
303
  expect(auth[:token][:query_parameter]).to eq(AuthSpecToken::Config.query_parameter.to_s)
302
304
 
303
305
  expect(auth[:token]).to have_key(:resources)
304
306
  expect(auth[:token][:resources]).to have_key(:token)
307
+
308
+ resource = auth[:token][:resources][:token]
309
+ expect(resource[:description]).to eq('Spravovat autentizační tokeny')
310
+ expect(resource[:actions][:request][:description]).to eq('Vyžádat autentizační token')
311
+ expect(resource[:actions][:revoke][:description]).to eq('Zneplatnit aktuální autentizační token')
312
+ expect(resource[:actions][:renew][:description]).to eq('Obnovit aktuální autentizační token')
305
313
  end
306
314
  end
307
315
 
@@ -113,7 +113,7 @@ describe HaveAPI::Extensions::ExceptionMailer do
113
113
 
114
114
  expect(last_response.status).to eq(500)
115
115
  expect(api_response).not_to be_ok
116
- expect(api_response.message).to eq('Server error occurred')
116
+ expect(api_response.message).to eq('A server error occurred')
117
117
 
118
118
  expect(calls.size).to eq(1)
119
119
  context, exception, body = calls.first
@@ -190,6 +190,6 @@ describe HaveAPI::Extensions::ExceptionMailer do
190
190
 
191
191
  expect(last_response.status).to eq(500)
192
192
  expect(api_response).not_to be_ok
193
- expect(api_response.message).to eq('Server error occurred')
193
+ expect(api_response.message).to eq('A server error occurred')
194
194
  end
195
195
  end
data/spec/i18n_spec.rb CHANGED
@@ -10,6 +10,16 @@ module I18nSpec
10
10
  User.new(:cs) if username == 'user' && password == 'pass'
11
11
  end
12
12
  end
13
+
14
+ module ActionStateBackend
15
+ def self.list_pending(*)
16
+ []
17
+ end
18
+
19
+ def self.new(*)
20
+ nil
21
+ end
22
+ end
13
23
  end
14
24
 
15
25
  describe HaveAPI::I18n do
@@ -113,8 +123,8 @@ describe HaveAPI::I18n do
113
123
  header 'Accept', 'application/json'
114
124
  call_api(:post, '/v1/things', thing: {})
115
125
 
116
- expect(api_response.message).to eq('input parameters not valid')
117
- expect(api_response.errors[:name]).to include('required parameter missing')
126
+ expect(api_response.message).to eq('input parameters are not valid')
127
+ expect(api_response.errors[:name]).to include('required parameter is missing')
118
128
  expect(last_response.headers['Vary']).to include('Accept-Language')
119
129
  end
120
130
 
@@ -123,9 +133,9 @@ describe HaveAPI::I18n do
123
133
  header 'Accept-Language', 'cs'
124
134
  call_api(:post, '/v1/things', thing: { count: 'nope' })
125
135
 
126
- expect(api_response.message).to eq('vstupní parametry nejsou platné')
127
- expect(api_response.errors[:name]).to include('povinný parametr chybí')
128
- expect(api_response.errors[:count].first).to include('neplatné celé číslo')
136
+ expect(api_response.message).to eq('vstupní parametry jsou neplatné')
137
+ expect(api_response.errors[:name]).to include('chybí povinný parametr')
138
+ expect(api_response.errors[:count].first).to include('není platné celé číslo')
129
139
  expect(last_response.headers['Vary']).to include('Accept-Language')
130
140
  end
131
141
 
@@ -151,7 +161,7 @@ describe HaveAPI::I18n do
151
161
  options '/v1/things', method: 'POST'
152
162
 
153
163
  length = api_response[:input][:parameters][:name][:validators][:length]
154
- expect(length[:message]).to eq('délka musí být v rozsahu <3, 5>')
164
+ expect(length[:message]).to eq('délka musí být v rozsahu 35')
155
165
  end
156
166
 
157
167
  it 'keeps untranslated array choices unchanged in OPTIONS responses' do
@@ -393,7 +403,7 @@ describe HaveAPI::I18n do
393
403
  create = api_response[:resources][:thing][:actions][:create]
394
404
  no_meta = create[:meta][:global][:input][:parameters][:no]
395
405
 
396
- expect(no_meta[:label]).to eq('Zakázat metadata')
406
+ expect(no_meta[:label]).to eq('Vypnout metadata')
397
407
  end
398
408
 
399
409
  it 'localizes application-supplied lazy validator messages' do
@@ -459,7 +469,7 @@ describe HaveAPI::I18n do
459
469
  expect(HaveAPI.localize(data)).to eq({
460
470
  message: 'Akce nebyla nalezena',
461
471
  errors: {
462
- name: ['povinný parametr chybí']
472
+ name: ['chybí povinný parametr']
463
473
  }
464
474
  })
465
475
  ensure
@@ -492,6 +502,39 @@ describe HaveAPI::I18n do
492
502
  end
493
503
  end
494
504
 
505
+ context 'with localized framework self-description' do
506
+ empty_api
507
+ use_version 1
508
+ default_version 1
509
+ auth_chain I18nSpec::Provider
510
+ action_state I18nSpec::ActionStateBackend
511
+
512
+ before do
513
+ header 'Accept', 'application/json'
514
+ header 'Accept-Language', 'cs'
515
+ end
516
+
517
+ it 'localizes authentication provider descriptions' do
518
+ call_api(:options, '/?describe=default')
519
+
520
+ description = api_response[:authentication][:basic][:description]
521
+ expect(description).to start_with('Autentizace pomocí HTTP Basic')
522
+ end
523
+
524
+ it 'localizes ActionState resource and action descriptions' do
525
+ call_api(:options, '/?describe=default')
526
+
527
+ action_state = api_response[:resources][:action_state]
528
+ expect(action_state[:description]).to eq('Procházet stavy blokujících akcí')
529
+ expect(action_state[:actions][:index][:description]).to eq('Vypsat stavy čekajících akcí')
530
+ expect(action_state[:actions][:poll][:description]).to eq(
531
+ 'Vrátit stav po dokončení akce, změně průběhu nebo vypršení časového limitu'
532
+ )
533
+ expect(action_state[:actions][:show][:description]).to eq('Zobrazit stav čekající akce')
534
+ expect(action_state[:actions][:cancel][:description]).to eq('Zrušit čekající akci')
535
+ end
536
+ end
537
+
495
538
  context 'with an authenticated locale resolver' do
496
539
  api do
497
540
  define_resource(:Thing) do
@@ -525,7 +568,7 @@ describe HaveAPI::I18n do
525
568
 
526
569
  action = api_response[:resources][:thing][:actions][:create]
527
570
  length = action.dig(:input, :parameters, :name, :validators, :length)
528
- expect(length[:message]).to eq('délka musí být v rozsahu <3, 5>')
571
+ expect(length[:message]).to eq('délka musí být v rozsahu 35')
529
572
  end
530
573
  end
531
574
 
@@ -869,23 +869,23 @@ describe HaveAPI::ModelAdapters::ActiveRecord do
869
869
 
870
870
  expect do
871
871
  described_class::Input.clean(ARAdapterSpec::Environment, 'abc', {})
872
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
872
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
873
873
 
874
874
  expect do
875
875
  described_class::Input.clean(ARAdapterSpec::Environment, '', {})
876
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
876
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
877
877
 
878
878
  expect do
879
879
  described_class::Input.clean(ARAdapterSpec::Environment, 1.2, {})
880
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
880
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
881
881
 
882
882
  expect do
883
883
  described_class::Input.clean(ARAdapterSpec::Environment, false, {})
884
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
884
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
885
885
 
886
886
  expect do
887
887
  described_class::Input.clean(ARAdapterSpec::Environment, true, {})
888
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
888
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
889
889
 
890
890
  expect do
891
891
  described_class::Input.clean(ARAdapterSpec::Environment, 9999, {})
@@ -913,11 +913,11 @@ describe HaveAPI::ModelAdapters::ActiveRecord do
913
913
 
914
914
  expect do
915
915
  described_class::Input.clean(ARAdapterSpec::StringAccount, %w[acct-alpha acct-beta], {})
916
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
916
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
917
917
 
918
918
  expect do
919
919
  described_class::Input.clean(ARAdapterSpec::StringAccount, { id: 'acct-alpha' }, {})
920
- end.to raise_error(HaveAPI::ValidationError, /not a valid id/)
920
+ end.to raise_error(HaveAPI::ValidationError, /not a valid ID/)
921
921
  end
922
922
 
923
923
  it 'rejects non-string includes metadata entries' do
@@ -957,7 +957,7 @@ describe HaveAPI::ModelAdapters::ActiveRecord do
957
957
  expect(last_response.status).to eq(200)
958
958
  expect(api_response).not_to be_ok
959
959
  expect(api_response.errors[:limit].first).to include(
960
- "range <0, #{HaveAPI::Actions::Paginable::MAX_LIMIT}>"
960
+ "between 0 and #{HaveAPI::Actions::Paginable::MAX_LIMIT}"
961
961
  )
962
962
  end
963
963
 
@@ -97,7 +97,7 @@ describe HaveAPI::Server do
97
97
 
98
98
  expect(last_response.status).to eq(400)
99
99
  expect(api_response).not_to be_ok
100
- expect(api_response.message).to match(/Bad JSON syntax/)
100
+ expect(api_response.message).to match(/Invalid JSON syntax/)
101
101
  end
102
102
 
103
103
  it 'returns 400 for non-object JSON bodies' do
@@ -109,7 +109,7 @@ describe HaveAPI::Server do
109
109
 
110
110
  expect(last_response.status).to eq(400)
111
111
  expect(api_response).not_to be_ok
112
- expect(api_response.message).to eq('JSON body must be an object')
112
+ expect(api_response.message).to eq('The JSON request body must be an object')
113
113
  end
114
114
  end
115
115
 
@@ -132,7 +132,7 @@ describe HaveAPI::Server do
132
132
 
133
133
  expect(last_response.status).to eq(415)
134
134
  expect(api_response).not_to be_ok
135
- expect(api_response.message).to eq('Unsupported Content-Type')
135
+ expect(api_response.message).to eq('Unsupported Content-Type header')
136
136
  expect(ServerIntegrationSpec::State.writes).to be_empty
137
137
  end
138
138
 
@@ -145,7 +145,7 @@ describe HaveAPI::Server do
145
145
 
146
146
  expect(last_response.status).to eq(400)
147
147
  expect(api_response).not_to be_ok
148
- expect(api_response.message).to eq('Bad Accept header')
148
+ expect(api_response.message).to eq('Invalid Accept header')
149
149
  end
150
150
 
151
151
  it 'returns JSON envelope for unknown route' do
@@ -169,7 +169,7 @@ describe HaveAPI::Server do
169
169
 
170
170
  expect(last_response.status).to eq(500)
171
171
  expect(api_response).not_to be_ok
172
- expect(api_response.message).to eq('Server error occurred')
172
+ expect(api_response.message).to eq('A server error occurred')
173
173
 
174
174
  expect(calls.size).to eq(1)
175
175
  context, exception = calls.first
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: haveapi
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.29.2
4
+ version: 0.29.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jakub Skokan
@@ -29,14 +29,14 @@ dependencies:
29
29
  requirements:
30
30
  - - "~>"
31
31
  - !ruby/object:Gem::Version
32
- version: 0.29.2
32
+ version: 0.29.3
33
33
  type: :runtime
34
34
  prerelease: false
35
35
  version_requirements: !ruby/object:Gem::Requirement
36
36
  requirements:
37
37
  - - "~>"
38
38
  - !ruby/object:Gem::Version
39
- version: 0.29.2
39
+ version: 0.29.3
40
40
  - !ruby/object:Gem::Dependency
41
41
  name: i18n
42
42
  requirement: !ruby/object:Gem::Requirement