mobility 1.0.0.alpha → 1.0.1

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.
Files changed (76) hide show
  1. checksums.yaml +4 -4
  2. checksums.yaml.gz.sig +0 -0
  3. data.tar.gz.sig +0 -0
  4. data/CHANGELOG.md +54 -1
  5. data/Gemfile +5 -16
  6. data/Gemfile.lock +30 -82
  7. data/README.md +24 -29
  8. data/lib/mobility.rb +67 -9
  9. data/lib/mobility/backend.rb +8 -10
  10. data/lib/mobility/backends.rb +1 -1
  11. data/lib/mobility/backends/active_record.rb +1 -1
  12. data/lib/mobility/backends/active_record/column.rb +1 -1
  13. data/lib/mobility/backends/active_record/container.rb +6 -9
  14. data/lib/mobility/backends/active_record/hstore.rb +4 -4
  15. data/lib/mobility/backends/active_record/json.rb +3 -3
  16. data/lib/mobility/backends/active_record/jsonb.rb +3 -3
  17. data/lib/mobility/backends/active_record/key_value.rb +27 -11
  18. data/lib/mobility/backends/active_record/serialized.rb +4 -0
  19. data/lib/mobility/backends/active_record/table.rb +12 -7
  20. data/lib/mobility/backends/container.rb +10 -2
  21. data/lib/mobility/backends/hash_valued.rb +4 -0
  22. data/lib/mobility/backends/jsonb.rb +1 -1
  23. data/lib/mobility/backends/key_value.rb +12 -15
  24. data/lib/mobility/backends/sequel.rb +34 -2
  25. data/lib/mobility/backends/sequel/container.rb +8 -8
  26. data/lib/mobility/backends/sequel/hstore.rb +1 -1
  27. data/lib/mobility/backends/sequel/json.rb +1 -0
  28. data/lib/mobility/backends/sequel/key_value.rb +79 -12
  29. data/lib/mobility/backends/sequel/pg_hash.rb +6 -6
  30. data/lib/mobility/backends/sequel/serialized.rb +4 -0
  31. data/lib/mobility/backends/sequel/table.rb +18 -8
  32. data/lib/mobility/backends/table.rb +29 -29
  33. data/lib/mobility/pluggable.rb +21 -1
  34. data/lib/mobility/plugin.rb +2 -2
  35. data/lib/mobility/plugins.rb +2 -0
  36. data/lib/mobility/plugins/active_model/dirty.rb +11 -5
  37. data/lib/mobility/plugins/active_record.rb +3 -0
  38. data/lib/mobility/plugins/active_record/backend.rb +2 -0
  39. data/lib/mobility/plugins/active_record/query.rb +7 -7
  40. data/lib/mobility/plugins/active_record/uniqueness_validation.rb +5 -1
  41. data/lib/mobility/plugins/arel.rb +125 -0
  42. data/lib/mobility/plugins/arel/nodes.rb +15 -0
  43. data/lib/mobility/plugins/arel/nodes/pg_ops.rb +134 -0
  44. data/lib/mobility/plugins/attribute_methods.rb +1 -0
  45. data/lib/mobility/plugins/attributes.rb +17 -15
  46. data/lib/mobility/plugins/backend.rb +45 -22
  47. data/lib/mobility/plugins/cache.rb +12 -5
  48. data/lib/mobility/plugins/default.rb +1 -1
  49. data/lib/mobility/plugins/fallbacks.rb +4 -4
  50. data/lib/mobility/plugins/fallthrough_accessors.rb +5 -6
  51. data/lib/mobility/plugins/locale_accessors.rb +2 -5
  52. data/lib/mobility/plugins/presence.rb +1 -1
  53. data/lib/mobility/plugins/reader.rb +2 -2
  54. data/lib/mobility/plugins/sequel/dirty.rb +2 -2
  55. data/lib/mobility/plugins/writer.rb +1 -1
  56. data/lib/mobility/version.rb +2 -2
  57. data/lib/rails/generators/mobility/templates/create_string_translations.rb +0 -1
  58. data/lib/rails/generators/mobility/templates/create_text_translations.rb +0 -1
  59. data/lib/rails/generators/mobility/templates/initializer.rb +11 -3
  60. metadata +14 -20
  61. metadata.gz.sig +0 -0
  62. data/lib/mobility/active_record/model_translation.rb +0 -14
  63. data/lib/mobility/active_record/string_translation.rb +0 -10
  64. data/lib/mobility/active_record/text_translation.rb +0 -10
  65. data/lib/mobility/active_record/translation.rb +0 -14
  66. data/lib/mobility/arel.rb +0 -49
  67. data/lib/mobility/arel/nodes.rb +0 -13
  68. data/lib/mobility/arel/nodes/pg_ops.rb +0 -132
  69. data/lib/mobility/arel/visitor.rb +0 -61
  70. data/lib/mobility/sequel/column_changes.rb +0 -28
  71. data/lib/mobility/sequel/hash_initializer.rb +0 -21
  72. data/lib/mobility/sequel/model_translation.rb +0 -20
  73. data/lib/mobility/sequel/sql.rb +0 -16
  74. data/lib/mobility/sequel/string_translation.rb +0 -10
  75. data/lib/mobility/sequel/text_translation.rb +0 -10
  76. data/lib/mobility/sequel/translation.rb +0 -53
@@ -100,7 +100,7 @@ On top of this, a backend will normally:
100
100
  # @param [Symbol] locale Locale to read
101
101
  # @return [TrueClass,FalseClass] Whether translation is present for locale
102
102
  def present?(locale, options = {})
103
- Util.present?(read(locale, options))
103
+ Util.present?(read(locale, **options))
104
104
  end
105
105
 
106
106
  # @!method model_class
@@ -120,6 +120,13 @@ On top of this, a backend will normally:
120
120
 
121
121
  # Defines setup hooks for backend to customize model class.
122
122
  module ClassMethods
123
+ # Returns valid option keys for this backend. This is overriden in
124
+ # backends to define which keys are valid for each backend class.
125
+ # @return [Array]
126
+ def valid_keys
127
+ []
128
+ end
129
+
123
130
  # Assign block to be called on model class.
124
131
  # @yield [attribute_names, options]
125
132
  # @note When called multiple times, setup blocks will be appended
@@ -179,15 +186,6 @@ On top of this, a backend will normally:
179
186
  EOM
180
187
  end
181
188
 
182
- # Called from plugins to apply custom processing for this backend.
183
- # Name is the name of the plugin.
184
- # @param [Symbol] name Name of plugin
185
- # @return [Boolean] Whether the plugin was applied
186
- # @note This is currently only called by Plugins::Cache.
187
- def apply_plugin(_)
188
- false
189
- end
190
-
191
189
  # Show useful information about this backend class, if it has no name.
192
190
  # @return [String]
193
191
  def inspect
@@ -5,7 +5,7 @@ module Mobility
5
5
  class << self
6
6
  # @param [Symbol, Object] backend Name of backend to load.
7
7
  def load_backend(name)
8
- return name if Module === name
8
+ return name if Module === name || name.nil?
9
9
 
10
10
  unless (backend = @backends[name])
11
11
  require "mobility/backends/#{name}"
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
  require "mobility/backend"
3
- require "mobility/arel"
3
+ require "mobility/plugins/arel"
4
4
 
5
5
  module Mobility
6
6
  module Backends
@@ -57,7 +57,7 @@ can be run again to add new attributes or locales.)
57
57
  # on model table
58
58
  def self.build_node(attr, locale)
59
59
  model_class.arel_table[Column.column_name_for(attr, locale)]
60
- .extend(::Mobility::Arel::MobilityExpressions)
60
+ .extend(Plugins::Arel::MobilityExpressions)
61
61
  end
62
62
 
63
63
  private
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
  require "mobility/backends/active_record"
3
- require "mobility/arel/nodes/pg_ops"
3
+ require "mobility/backends/container"
4
+ require "mobility/plugins/arel/nodes/pg_ops"
4
5
 
5
6
  module Mobility
6
7
  module Backends
@@ -11,11 +12,7 @@ Implements the {Mobility::Backends::Container} backend for ActiveRecord models.
11
12
  =end
12
13
  class ActiveRecord::Container
13
14
  include ActiveRecord
14
-
15
- # @!method column_name
16
- # Returns name of json or jsonb column used to store translations
17
- # @return [Symbol] (:translations) Name of translations column
18
- option_reader :column_name
15
+ include Container
19
16
 
20
17
  # @!group Backend Accessors
21
18
  #
@@ -52,15 +49,15 @@ Implements the {Mobility::Backends::Container} backend for ActiveRecord models.
52
49
 
53
50
  # @param [String] attr Attribute name
54
51
  # @param [Symbol] locale Locale
55
- # @return [Mobility::Arel::Nodes::Json,Mobility::Arel::Nodes::Jsonb] Arel
52
+ # @return [Mobility::Plugins::Arel::Nodes::Json,Mobility::Arel::Nodes::Jsonb] Arel
56
53
  # node for attribute on json or jsonb column
57
54
  def build_node(attr, locale)
58
55
  column = model_class.arel_table[column_name]
59
56
  case column_type
60
57
  when :json
61
- Arel::Nodes::JsonContainer.new(column, build_quoted(locale), build_quoted(attr))
58
+ Plugins::Arel::Nodes::JsonContainer.new(column, build_quoted(locale), build_quoted(attr))
62
59
  when :jsonb
63
- Arel::Nodes::JsonbContainer.new(column, build_quoted(locale), build_quoted(attr))
60
+ Plugins::Arel::Nodes::JsonbContainer.new(column, build_quoted(locale), build_quoted(attr))
64
61
  end
65
62
  end
66
63
 
@@ -1,5 +1,5 @@
1
1
  require 'mobility/backends/active_record/pg_hash'
2
- require 'mobility/arel/nodes/pg_ops'
2
+ require 'mobility/plugins/arel/nodes/pg_ops'
3
3
 
4
4
  module Mobility
5
5
  module Backends
@@ -18,17 +18,17 @@ Implements the {Mobility::Backends::Hstore} backend for ActiveRecord models.
18
18
 
19
19
  # @!macro backend_writer
20
20
  def write(locale, value, options = {})
21
- super(locale, value && value.to_s, options)
21
+ super(locale, value && value.to_s, **options)
22
22
  end
23
23
  # @!endgroup
24
24
 
25
25
  # @param [String] attr Attribute name
26
26
  # @param [Symbol] locale Locale
27
- # @return [Mobility::Arel::Nodes::Hstore] Arel node for value of
27
+ # @return [Mobility::Plugins::Arel::Nodes::Hstore] Arel node for value of
28
28
  # attribute key on hstore column
29
29
  def self.build_node(attr, locale)
30
30
  column_name = column_affix % attr
31
- Arel::Nodes::Hstore.new(model_class.arel_table[column_name], build_quoted(locale))
31
+ Plugins::Arel::Nodes::Hstore.new(model_class.arel_table[column_name], build_quoted(locale))
32
32
  end
33
33
  end
34
34
  end
@@ -1,5 +1,5 @@
1
1
  require 'mobility/backends/active_record/pg_hash'
2
- require 'mobility/arel/nodes/pg_ops'
2
+ require 'mobility/plugins/arel/nodes/pg_ops'
3
3
 
4
4
  module Mobility
5
5
  module Backends
@@ -32,11 +32,11 @@ Implements the {Mobility::Backends::Json} backend for ActiveRecord models.
32
32
 
33
33
  # @param [String] attr Attribute name
34
34
  # @param [Symbol] locale Locale
35
- # @return [Mobility::Arel::Nodes::Json] Arel node for value of
35
+ # @return [Mobility::Plugins::Arel::Nodes::Json] Arel node for value of
36
36
  # attribute key on jsonb column
37
37
  def self.build_node(attr, locale)
38
38
  column_name = column_affix % attr
39
- Arel::Nodes::Json.new(model_class.arel_table[column_name], build_quoted(locale))
39
+ Plugins::Arel::Nodes::Json.new(model_class.arel_table[column_name], build_quoted(locale))
40
40
  end
41
41
  end
42
42
  end
@@ -1,5 +1,5 @@
1
1
  require 'mobility/backends/active_record/pg_hash'
2
- require 'mobility/arel/nodes/pg_ops'
2
+ require 'mobility/plugins/arel/nodes/pg_ops'
3
3
 
4
4
  module Mobility
5
5
  module Backends
@@ -32,11 +32,11 @@ Implements the {Mobility::Backends::Jsonb} backend for ActiveRecord models.
32
32
 
33
33
  # @param [String] attr Attribute name
34
34
  # @param [Symbol] locale Locale
35
- # @return [Mobility::Arel::Nodes::Jsonb] Arel node for value of
35
+ # @return [Mobility::Plugins::Arel::Nodes::Jsonb] Arel node for value of
36
36
  # attribute key on jsonb column
37
37
  def self.build_node(attr, locale)
38
38
  column_name = column_affix % attr
39
- Arel::Nodes::Jsonb.new(model_class.arel_table[column_name], build_quoted(locale))
39
+ Plugins::Arel::Nodes::Jsonb.new(model_class.arel_table[column_name], build_quoted(locale))
40
40
  end
41
41
  end
42
42
  end
@@ -1,8 +1,6 @@
1
1
  # frozen-string-literal: true
2
2
  require "mobility/backends/active_record"
3
3
  require "mobility/backends/key_value"
4
- require "mobility/active_record/string_translation"
5
- require "mobility/active_record/text_translation"
6
4
 
7
5
  module Mobility
8
6
  module Backends
@@ -37,21 +35,21 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
37
35
  super
38
36
  if type = options[:type]
39
37
  options[:association_name] ||= :"#{options[:type]}_translations"
40
- options[:class_name] ||= Mobility::ActiveRecord.const_get("#{type.capitalize}Translation")
38
+ options[:class_name] ||= const_get("#{type.capitalize}Translation")
41
39
  end
42
40
  options[:table_alias_affix] = "#{model_class}_%s_#{options[:association_name]}"
43
41
  rescue NameError
44
- raise ArgumentError, "You must define a Mobility::ActiveRecord::#{type.capitalize}Translation class."
42
+ raise ArgumentError, "You must define a Mobility::Backends::ActiveRecord::KeyValue::#{type.capitalize}Translation class."
45
43
  end
46
44
  # @!endgroup
47
45
 
48
46
  # @param [String] attr Attribute name
49
47
  # @param [Symbol] _locale Locale
50
- # @return [Mobility::Arel::Attribute] Arel attribute for aliased
48
+ # @return [Mobility::Plugins::Arel::Attribute] Arel attribute for aliased
51
49
  # translation table value column
52
50
  def build_node(attr, locale)
53
51
  aliased_table = class_name.arel_table.alias(table_alias(attr, locale))
54
- Arel::Attribute.new(aliased_table, :value, locale, self, attribute_name: attr.to_sym)
52
+ Plugins::Arel::Attribute.new(aliased_table, :value, locale, self, attr.to_sym)
55
53
  end
56
54
 
57
55
  # Joins translations using either INNER/OUTER join appropriate to the query.
@@ -119,7 +117,7 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
119
117
  # The title predicate has a non-nil value, so we can use an INNER JOIN,
120
118
  # whereas we are searching for nil content, which requires an OUTER JOIN.
121
119
  #
122
- class Visitor < ::Mobility::Arel::Visitor
120
+ class Visitor < Plugins::Arel::Visitor
123
121
  private
124
122
 
125
123
  def visit_Arel_Nodes_Equality(object)
@@ -141,7 +139,7 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
141
139
  transform_values { OUTER_JOIN }
142
140
  end
143
141
 
144
- def visit_Mobility_Arel_Attribute(object)
142
+ def visit_Mobility_Plugins_Arel_Attribute(object)
145
143
  if object.backend_class == backend_class && object.locale == locale
146
144
  { object.attribute_name => OUTER_JOIN }
147
145
  end
@@ -194,8 +192,8 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
194
192
 
195
193
  # Returns translation for a given locale, or builds one if none is present.
196
194
  # @param [Symbol] locale
197
- # @return [Mobility::ActiveRecord::TextTranslation,Mobility::ActiveRecord::StringTranslation]
198
- def translation_for(locale, _options = {})
195
+ # @return [Mobility::Backends::ActiveRecord::KeyValue::TextTranslation,Mobility::Backends::ActiveRecord::KeyValue::StringTranslation]
196
+ def translation_for(locale, **)
199
197
  translation = translations.find { |t| t.key == attribute && t.locale == locale.to_s }
200
198
  translation ||= translations.build(locale: locale, key: attribute)
201
199
  translation
@@ -205,12 +203,30 @@ Implements the {Mobility::Backends::KeyValue} backend for ActiveRecord models.
205
203
  def self.included(model_class)
206
204
  model_class.after_destroy do
207
205
  [:string, :text].each do |type|
208
- Mobility::ActiveRecord.const_get("#{type.capitalize}Translation").
206
+ Mobility::Backends::ActiveRecord::KeyValue.const_get("#{type.capitalize}Translation").
209
207
  where(translatable: self).destroy_all
210
208
  end
211
209
  end
212
210
  end
213
211
  end
212
+
213
+ class Translation < ::ActiveRecord::Base
214
+ self.abstract_class = true
215
+
216
+ belongs_to :translatable, polymorphic: true, touch: true
217
+
218
+ validates :key, presence: true, uniqueness: { scope: [:translatable_id, :translatable_type, :locale], case_sensitive: true }
219
+ validates :translatable, presence: true
220
+ validates :locale, presence: true
221
+ end
222
+
223
+ class TextTranslation < Translation
224
+ self.table_name = "mobility_text_translations"
225
+ end
226
+
227
+ class StringTranslation < Translation
228
+ self.table_name = "mobility_string_translations"
229
+ end
214
230
  end
215
231
 
216
232
  register_backend(:active_record_key_value, ActiveRecord::KeyValue)
@@ -30,6 +30,10 @@ Implements {Mobility::Backends::Serialized} backend for ActiveRecord models.
30
30
  include ActiveRecord
31
31
  include HashValued
32
32
 
33
+ def self.valid_keys
34
+ super + [:format]
35
+ end
36
+
33
37
  # @!group Backend Configuration
34
38
  # @param (see Backends::Serialized.configure)
35
39
  # @option (see Backends::Serialized.configure)
@@ -1,7 +1,6 @@
1
1
  # frozen-string-literal: true
2
2
  require "mobility/backends/active_record"
3
3
  require "mobility/backends/table"
4
- require "mobility/active_record/model_translation"
5
4
 
6
5
  module Mobility
7
6
  module Backends
@@ -116,10 +115,10 @@ columns to that table.
116
115
 
117
116
  # @param [String] attr Attribute name
118
117
  # @param [Symbol] _locale Locale
119
- # @return [Mobility::Arel::Attribute] Arel node for column on translation table
118
+ # @return [Mobility::Plugins::Arel::Attribute] Arel node for column on translation table
120
119
  def build_node(attr, locale)
121
120
  aliased_table = model_class.const_get(subclass_name).arel_table.alias(table_alias(locale))
122
- Arel::Attribute.new(aliased_table, attr, locale, self)
121
+ Plugins::Arel::Attribute.new(aliased_table, attr, locale, self)
123
122
  end
124
123
 
125
124
  # Joins translations using either INNER/OUTER join appropriate to the
@@ -190,7 +189,7 @@ columns to that table.
190
189
  # we need an OUTER JOIN. In the second case, one attribute is matched
191
190
  # against a non-nil value, so we can use an INNER JOIN.
192
191
  #
193
- class Visitor < Arel::Visitor
192
+ class Visitor < Plugins::Arel::Visitor
194
193
  private
195
194
 
196
195
  def visit_Arel_Nodes_Equality(object)
@@ -227,7 +226,7 @@ columns to that table.
227
226
  end
228
227
  end
229
228
 
230
- def visit_Mobility_Arel_Attribute(object)
229
+ def visit_Mobility_Plugins_Arel_Attribute(object)
231
230
  # We compare table names here to ensure that attributes defined on
232
231
  # different backends but the same table will correctly get an OUTER
233
232
  # join when required. Use options[:table_name] here since we don't
@@ -245,7 +244,7 @@ columns to that table.
245
244
  if self.const_defined?(subclass_name, false)
246
245
  const_get(subclass_name, false)
247
246
  else
248
- const_set(subclass_name, Class.new(Mobility::ActiveRecord::ModelTranslation))
247
+ const_set(subclass_name, Class.new(Translation))
249
248
  end
250
249
 
251
250
  translation_class.table_name = options[:table_name]
@@ -283,7 +282,7 @@ columns to that table.
283
282
 
284
283
  # Returns translation for a given locale, or builds one if none is present.
285
284
  # @param [Symbol] locale
286
- def translation_for(locale, _)
285
+ def translation_for(locale, **)
287
286
  translation = translations.in_locale(locale)
288
287
  translation ||= translations.build(locale: locale)
289
288
  translation
@@ -303,6 +302,12 @@ columns to that table.
303
302
  destroy(empty_translations) if empty_translations.any?
304
303
  end
305
304
  end
305
+
306
+ # Subclassed dynamically to generate translation class.
307
+ class Translation < ::ActiveRecord::Base
308
+ self.abstract_class = true
309
+ validates :locale, presence: true
310
+ end
306
311
  end
307
312
 
308
313
  register_backend(:active_record_table, ActiveRecord::Table)
@@ -19,8 +19,16 @@ stored).
19
19
 
20
20
  =end
21
21
  module Container
22
+ def self.included(backend_class)
23
+ backend_class.extend ClassMethods
24
+ backend_class.option_reader :column_name
25
+ end
26
+
27
+ module ClassMethods
28
+ def valid_keys
29
+ [:column_name]
30
+ end
31
+ end
22
32
  end
23
-
24
- register_backend(:container, Container)
25
33
  end
26
34
  end
@@ -36,6 +36,10 @@ Defines read and write methods that access the value at a key with value
36
36
  end
37
37
 
38
38
  module ClassMethods
39
+ def valid_keys
40
+ [:column_prefix, :column_suffix]
41
+ end
42
+
39
43
  def configure(options)
40
44
  options[:column_affix] = "#{options[:column_prefix]}%s#{options[:column_suffix]}"
41
45
  end
@@ -6,7 +6,7 @@ Stores translations as hash on Postgres jsonb column.
6
6
 
7
7
  ==Backend Options
8
8
 
9
- ===+prefix+ and +suffix+
9
+ ===+column_prefix+ and +column_suffix+
10
10
 
11
11
  Prefix and suffix to add to attribute name to generate jsonb column name.
12
12
 
@@ -54,13 +54,13 @@ other backends on model (otherwise one will overwrite the other).
54
54
 
55
55
  # @!group Backend Accessors
56
56
  # @!macro backend_reader
57
- def read(locale, options = {})
58
- translation_for(locale, options).value
57
+ def read(locale, **options)
58
+ translation_for(locale, **options).value
59
59
  end
60
60
 
61
61
  # @!macro backend_writer
62
- def write(locale, value, options = {})
63
- translation_for(locale, options).value = value
62
+ def write(locale, value, **options)
63
+ translation_for(locale, **options).value = value
64
64
  end
65
65
  # @!endgroup
66
66
 
@@ -83,6 +83,10 @@ other backends on model (otherwise one will overwrite the other).
83
83
  end
84
84
 
85
85
  module ClassMethods
86
+ def valid_keys
87
+ [:type, :association_name, :class_name]
88
+ end
89
+
86
90
  # @!group Backend Configuration
87
91
  # @option options [Symbol,String] type Column type to use
88
92
  # @option options [Symbol] association_name (:<type>_translations) Name
@@ -100,16 +104,9 @@ other backends on model (otherwise one will overwrite the other).
100
104
  end
101
105
  end
102
106
 
103
- # Apply custom processing for plugin
104
- # @param (see Backend::ClassMethods#apply_plugin)
105
- # @return (see Backend::ClassMethods#apply_plugin)
106
- def apply_plugin(name)
107
- if name == :cache
108
- include self::Cache
109
- true
110
- else
111
- super
112
- end
107
+ # Apply custom processing for cache plugin
108
+ def include_cache
109
+ include self::Cache
113
110
  end
114
111
 
115
112
  def table_alias(attr, locale)
@@ -123,7 +120,7 @@ other backends on model (otherwise one will overwrite the other).
123
120
  if cache.has_key?(locale)
124
121
  cache[locale]
125
122
  else
126
- cache[locale] = super(locale, options)
123
+ cache[locale] = super(locale, **options)
127
124
  end
128
125
  end
129
126