storefront 0.2.1 → 0.2.7

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 (73) hide show
  1. data/Rakefile +2 -2
  2. data/lib/storefront.rb +21 -3
  3. data/lib/storefront/configuration.rb +154 -0
  4. data/lib/storefront/dashboard.rb +8 -7
  5. data/lib/storefront/form.rb +70 -53
  6. data/lib/storefront/form/base.rb +50 -0
  7. data/lib/storefront/form/builder.rb +124 -0
  8. data/lib/storefront/form/errors.rb +20 -46
  9. data/lib/storefront/form/field.rb +102 -0
  10. data/lib/storefront/form/fieldset.rb +44 -0
  11. data/lib/storefront/form/hint.rb +34 -0
  12. data/lib/storefront/form/input.rb +191 -0
  13. data/lib/storefront/form/inputs/checkbox.rb +12 -0
  14. data/lib/storefront/form/inputs/date.rb +16 -0
  15. data/lib/storefront/form/inputs/file.rb +12 -0
  16. data/lib/storefront/form/inputs/hidden.rb +11 -0
  17. data/lib/storefront/form/inputs/radio.rb +11 -0
  18. data/lib/storefront/form/inputs/range.rb +15 -0
  19. data/lib/storefront/form/inputs/select.rb +68 -0
  20. data/lib/storefront/form/inputs/string.rb +89 -0
  21. data/lib/storefront/form/inputs/submit.rb +24 -0
  22. data/lib/storefront/form/inputs/textarea.rb +19 -0
  23. data/lib/storefront/form/inputs/value.rb +16 -0
  24. data/lib/storefront/form/label.rb +35 -0
  25. data/lib/storefront/helpers/attribute_helper.rb +29 -8
  26. data/lib/storefront/helpers/body_helper.rb +1 -1
  27. data/lib/storefront/helpers/cache_helper.rb +2 -2
  28. data/lib/storefront/helpers/component_helper.rb +34 -19
  29. data/lib/storefront/helpers/dashboard_helper.rb +9 -17
  30. data/lib/storefront/helpers/definition_list_helper.rb +82 -14
  31. data/lib/storefront/helpers/form_helper.rb +7 -2
  32. data/lib/storefront/helpers/head_helper.rb +2 -2
  33. data/lib/storefront/helpers/image_helper.rb +1 -25
  34. data/lib/storefront/helpers/list_helper.rb +120 -32
  35. data/lib/storefront/helpers/locale_helper.rb +98 -28
  36. data/lib/storefront/helpers/page_helper.rb +78 -60
  37. data/lib/storefront/helpers/request_helper.rb +3 -0
  38. data/lib/storefront/helpers/table_helper.rb +1 -1
  39. data/lib/storefront/helpers/template_helper.rb +11 -0
  40. data/lib/storefront/helpers/time_helper.rb +2 -2
  41. data/lib/storefront/helpers/widget_helper.rb +153 -2
  42. data/lib/storefront/model_helper.rb +17 -0
  43. data/lib/storefront/proxies/attribute_proxy.rb +150 -0
  44. data/lib/storefront/proxies/model_proxy.rb +249 -0
  45. data/lib/storefront/railtie.rb +4 -2
  46. data/lib/storefront/table.rb +7 -0
  47. data/test/form_helper_test.rb +1 -1
  48. metadata +25 -27
  49. data/init.rb +0 -1
  50. data/lib/storefront/form/elements.rb +0 -101
  51. data/lib/storefront/form/fields.rb +0 -420
  52. data/lib/storefront/form/hints.rb +0 -18
  53. data/lib/storefront/form/inputs.rb +0 -258
  54. data/lib/storefront/form/labels.rb +0 -81
  55. data/lib/storefront/form/model.rb +0 -84
  56. data/lib/storefront/microdata/address.rb +0 -7
  57. data/lib/storefront/microdata/event.rb +0 -13
  58. data/lib/storefront/microdata/geo.rb +0 -7
  59. data/lib/storefront/microdata/organization.rb +0 -7
  60. data/lib/storefront/microdata/person.rb +0 -7
  61. data/lib/storefront/microformat/event.rb +0 -7
  62. data/lib/storefront/microformat/person.rb +0 -7
  63. data/lib/storefront/models/container.rb +0 -0
  64. data/lib/storefront/models/element.rb +0 -15
  65. data/lib/storefront/models/form.rb +0 -0
  66. data/lib/storefront/models/form_element.rb +0 -0
  67. data/lib/storefront/models/link.rb +0 -0
  68. data/lib/storefront/models/list.rb +0 -0
  69. data/lib/storefront/models/list_element.rb +0 -0
  70. data/lib/storefront/models/table.rb +0 -0
  71. data/lib/storefront/models/term.rb +0 -0
  72. data/lib/storefront/models/term_list.rb +0 -0
  73. data/lib/storefront/models/validation.rb +0 -0
@@ -3,35 +3,27 @@ module Storefront
3
3
  def dashboard_for(*args, &block)
4
4
  record = args.shift
5
5
  options = args.extract_options!
6
- condition = extract_condition!(options)
7
6
  @dashboard_record = record
8
- concat(capture(&block)) if record && condition != false
7
+ concat(capture(&block)) if record
9
8
  @dashboard_record = nil
10
9
  end
11
-
12
- def dashboard(key, locals = {})
13
- render :partial => key, :locals => locals.reverse_merge(:figures => [])
14
- end
15
-
10
+
16
11
  def figure(*names, &block)
17
12
  locals = names.extract_options!
18
- condition = extract_condition!(locals)
19
13
 
20
- if condition != false
21
- locals.reverse_merge(:locale => nil)
22
- locals.merge!(:yielded_content => capture(&block)) if block_given?
23
- result = capture_haml do
24
- names.each do |name|
25
- haml_concat render(:partial => "shared/dashboard/#{name}", :locals => locals)
26
- end
14
+ locals.reverse_merge(:locale => nil)
15
+ locals.merge!(:yielded_content => capture(&block)) if block_given?
16
+ result = capture_haml do
17
+ names.each do |name|
18
+ haml_concat render(:partial => "shared/dashboard/#{name}", :locals => locals)
27
19
  end
28
20
  end
29
21
 
30
22
  result
31
23
  end
32
-
24
+
33
25
  def report_for(record_or_key, hash, options = {}, &block)
34
- Semantic::Dashboard.new(self, record_or_key, hash, options, &block).content
26
+ Storefront::Dashboard.new(self, record_or_key, hash, options, &block).content
35
27
  end
36
28
  end
37
29
  end
@@ -1,29 +1,97 @@
1
1
  module Storefront
2
- module DefinitionListHelper
3
- def term(key, value, options = {})
4
- return if value.blank?
5
- condition = extract_condition!(options)
2
+ module DefinitionListHelper
3
+ def definition_list_widget(*args, &block)
4
+ options = definition_list_widget_options(*args)
5
+
6
+ capture_haml do
7
+ haml_tag options[:as], options[:outer_html] do
8
+ @separator = options.has_key?(:separator) ? options[:separator] : storefront_config.term_separator
9
+ header = header_widget(options)
10
+ haml_concat header.gsub(/\n$/, "") if header.present?
6
11
 
7
- if condition != false
8
- result = capture_haml do
9
- haml_tag :tr, :class => "term" do
10
- text = key.is_a?(String) ? key : t("widgets.details.#{key}")
11
- haml_tag :td, text.gsub(/:?$/, ":"), :class => "key first"
12
- haml_tag :td, value, :class => "value"
12
+ haml_tag options[:tag], options[:content_html], &block
13
+
14
+ if options[:footer_html].present?
15
+ haml_concat footer_widget(options[:footer_html])
13
16
  end
17
+ @separator = nil
14
18
  end
15
19
  end
20
+ end
21
+ alias terms_widget definition_list_widget
22
+
23
+ def definition_list_widget_options(*args)
24
+ options = widget_options("definition-list-widget", *args)
25
+
26
+ options[:as] ||= :section
27
+ options[:tag] ||= storefront_config.terms_tag
28
+
29
+ options[:content_html] ||= {}
30
+ merge_class! options[:content_html], storefront_config.content_class
31
+
32
+ options
33
+ end
34
+
35
+ def definition(key, value, options = {})
36
+ locale_options = options.delete(:locale_options) || {}
37
+ label = t?(key, locale_options.reverse_merge(:scope => :"terms.labels"))
38
+
39
+ key_html = options.delete(:key_html) || {}
40
+ value_html = options.delete(:value_html) || {}
41
+
42
+ key_html.reverse_merge! clone_attributes(options)
43
+ value_html.reverse_merge! clone_attributes(options)
44
+
45
+ merge_class! key_html, storefront_config.term_key_class
46
+ merge_class! value_html, storefront_config.term_value_class
47
+
48
+ id_base = label.underscore.strip.gsub(/[\s|_]+/, storefront_config.separator).squeeze(storefront_config.separator)
49
+
50
+ key_html[:id] ||= "#{id_base}-key"
51
+ value_html[:id] ||= "#{id_base}-value"
52
+
53
+ separator = options[:separator] || @separator
54
+
55
+ label.gsub!(/#{separator}?$/, separator) if separator.present?
56
+
57
+ if storefront_config.include_aria
58
+ value_html[:role] ||= :definition
59
+ value_html[:"aria-labelledby"] = key_html[:id]
60
+ #value_html[:"aria-describedby"] = hint_html[:id]
61
+ end
16
62
 
17
- result
63
+ if storefront_config.terms_tag == :table
64
+ _table_term(label, value, key_html, value_html)
65
+ else
66
+ _definiton_list_term(label, value, key_html, value_html)
67
+ end
18
68
  end
69
+ alias term definition
19
70
 
20
- def terms(&block)
71
+ def definition_list(&block)
21
72
  capture_haml do
22
- haml_tag :dl do
73
+ haml_tag storefront_config.terms_tag do
23
74
  yield
24
75
  end
25
76
  end
26
77
  end
27
- alias definition_list terms
78
+ alias terms definition_list
79
+
80
+ protected
81
+ def _definiton_list_term(label, value, key_html, value_html)
82
+ capture_haml do
83
+ haml_tag :dt, label, key_html
84
+ haml_tag :dd, value, value_html
85
+ end
86
+ end
87
+
88
+ def _table_term(label, value, key_html, value_html)
89
+ capture_haml do
90
+ haml_tag :tr, :class => storefront_config.term_class do
91
+ haml_tag :td, label, key_html
92
+ haml_tag :td, value, value_html
93
+ end
94
+ end
95
+ end
28
96
  end
29
97
  end
@@ -1,8 +1,13 @@
1
1
  module Storefront
2
2
  module FormHelper
3
3
  def form_for(*args, &block)
4
- Storefront::Form.new(self, *args, &block).content
4
+ Storefront::Form.new(self, *args).render(&block)
5
+ end
6
+
7
+ def submit_for(text, url, options = {})
8
+ form_for(object, options.merge(:url => url)) do |form|
9
+ haml_concat Storefront::Form::Input.find(:submit).new(:value => text).render
10
+ end
5
11
  end
6
12
  end
7
13
  end
8
-
@@ -193,7 +193,7 @@ module Storefront
193
193
  def content_type_tag(type = "text/html", charset = "UTF-8")
194
194
  meta_tag("Content-Type", "#{type}; charset=#{charset}")
195
195
  end
196
-
196
+
197
197
  def search_link_tag(href, title)
198
198
  link_tag({:rel => "search", :type => "application/opensearchdescription+xml", :href => href, :title => title})
199
199
  end
@@ -201,7 +201,7 @@ module Storefront
201
201
  def favicon_link_tag(favicon = "/favicon.ico")
202
202
  link_tag({:rel => "shortcut icon", :href => favicon, :type => "image/x-icon"})
203
203
  end
204
-
204
+
205
205
  def link_tag(options = {})
206
206
  tag(:link, options)
207
207
  end
@@ -20,31 +20,7 @@ module Storefront
20
20
 
21
21
  tag("img", options)
22
22
  end
23
-
24
- def load_logo(parent, size = "small", link = nil, lightbox = true)
25
- if parent && parent.logo_id.present?
26
- path = parent.logo.url(size.to_s) rescue nil
27
- end
28
-
29
- if path.blank?
30
- path = "/images/vendors/no-logo.png"
31
- alt = "No logo"
32
- else
33
- alt = "Logo for #{parent.is_a?(::Group) ? parent.name : parent.vendor_name}"
34
- end
35
-
36
- if parent && parent.logo
37
- path << "?#{parent.logo.updated_at.to_i}"
38
- end
39
- if link
40
- # , :width => 74, :height => 74
41
- clazz = lightbox == true ? 'fancy-ajax logo' : 'logo'
42
- link_to [content_tag(:span), image_tag(path, :class => "photo", :alt => alt, :title => alt)].join("").html_safe, link, :class => clazz, :"data-deal-id" => parent.id, :"data-ajax" => "false"
43
- else
44
- image_tag(path)
45
- end
46
- end
47
-
23
+
48
24
  # http://snippets.dzone.com/posts/show/805
49
25
  def read_image_size(path)
50
26
  width, height = IO.read("#{Rails.root}/public/images/#{path}")[0x10..0x18].unpack('NN')
@@ -1,47 +1,135 @@
1
1
  module Storefront
2
2
  module ListHelper
3
- def nav(key, path = nil, attributes = {}, &block)
4
- condition = extract_condition!(attributes)
5
- return if condition == false
6
- text = widget_text(key, :nav)
3
+ def list_widget(*args, &block)
4
+ options = list_widget_options("list-widget", *args)
5
+
6
+ capture_haml do
7
+ haml_tag :nav, options[:outer_html] do
8
+ @list_context = :list
9
+
10
+ header = header_widget(options)
11
+ haml_concat header if header.present?
12
+
13
+ haml_tag options[:tag], options[:inner_html], &block
14
+
15
+ footer_widget(options[:footer_html]) if options[:footer_html].present?
16
+
17
+ @list_context = nil
18
+ end
19
+ end
20
+ end
21
+
22
+ def list_widget_options(*args)
23
+ options = widget_options(*args)
24
+
25
+ options[:tag] ||= :ul
26
+
27
+ if storefront_config.include_aria
28
+ options[:outer_html][:role] ||= :list
29
+ end
30
+
31
+ options[:inner_html] ||= {}
32
+
33
+ merge_class! options[:inner_html], *[
34
+ "list-items"
35
+ ]
36
+
37
+ options
38
+ end
39
+
40
+ def menu_widget(*args, &block)
41
+ options = menu_widget_options("menu-widget", *args)
42
+
43
+ capture_haml do
44
+ haml_tag :nav, options[:outer_html] do
45
+ @list_context = :menu
46
+ header = header_widget(options)
47
+ haml_concat header if header.present?
48
+
49
+ haml_tag options[:tag], options[:inner_html], &block
50
+
51
+ footer_widget(options[:footer_html]) if options[:footer_html].present?
52
+ @list_context = nil
53
+ end
54
+ end
55
+ end
56
+ alias nav_widget menu_widget
57
+
58
+ def menu_widget_options(*args)
59
+ options = widget_options(*args)
60
+
61
+ if storefront_config.include_aria
62
+ options[:outer_html][:role] ||= :menu
63
+ end
64
+
65
+ options[:inner_html] ||= {}
66
+
67
+ options[:tag] ||= :ol
68
+
69
+ merge_class! options[:inner_html], *[
70
+ "list-items"
71
+ ]
72
+
73
+ options
74
+ end
75
+
76
+ def list_item(key, path = nil, attributes = {}, &block)
77
+ locale_options = attributes.delete(:locale_options) || {}
78
+ text = t?(key, locale_options.reverse_merge(:scope => :"widgets.nav"))
79
+
80
+ as = attributes.delete(:as) || :span
81
+ separator = attributes.delete(:separator)
82
+
7
83
  if attributes.has_key?(:current)
8
- current = attributes.delete(:current) == true
84
+ current = attributes.delete(:current) == true
9
85
  else
10
- current = on_current_page?(path)
86
+ current = on_current_page?(path)
11
87
  end
12
- li_class = "primary-navigation-item"
13
- if current
14
- li_class << " active"
15
- attributes[:class] = [attributes[:class], "active"].compact.uniq.join(" ")
88
+
89
+ inner_html = attributes.delete(:inner_html) || {}
90
+ outer_html = attributes.delete(:outer_html) || {}
91
+
92
+ inner_html.merge! clone_attributes(attributes)
93
+
94
+ merge_class! outer_html, *[
95
+ storefront_config.nav_class,
96
+ current ? storefront_config.active_class : nil
97
+ ].compact.uniq
98
+
99
+ if storefront_config.include_aria
100
+ outer_html[:role] ||= case @list_context
101
+ when :list
102
+ :listitem
103
+ when :menu
104
+ :menuitem
105
+ else
106
+ :listitem
107
+ end
16
108
  end
17
- as = attributes.delete(:as) || :span
18
- li_class << " #{attributes.delete(:li_class)}" if attributes[:li_class]
19
- li_class = li_class.present? ? {:class => li_class} : nil
20
- separator = attributes.delete(:separator)
21
- checkbox = attributes.delete(:checkbox) == true
22
- result = capture_haml do
23
- haml_tag :li, li_class do
24
- if checkbox
25
- haml_tag :label, text.strip
26
- haml_tag :input, :type => "checkbox"
27
- else
28
- if block_given?
29
- case block.arity
30
- when 1
31
- yield(text.strip)
32
- else
33
- yield
34
- end
35
- elsif current && as == :span
36
- haml_tag :span, text.strip, attributes
109
+
110
+ text.strip!
111
+
112
+ outer_html[:id] ||= [text.underscore.parameterize, storefront_config.nav_class].join(storefront_config.separator).gsub(/[\s|_]+/, storefront_config.separator).squeeze(storefront_config.separator)
113
+
114
+ capture_haml do
115
+ haml_tag storefront_config.nav_tag, outer_html do
116
+ if block_given?
117
+ case block.arity
118
+ when 1
119
+ yield(text.strip)
37
120
  else
38
- haml_concat link_to(text.strip, path, attributes)
121
+ yield
39
122
  end
123
+ elsif current && as == :span
124
+ haml_tag :span, text, inner_html
125
+ else
126
+ inner_html[:title] ||= "Link to the #{text.strip} page."
127
+ haml_concat link_to(text, path, inner_html)
40
128
  end
41
129
  haml_tag :span, separator if separator
42
130
  end
43
131
  end
44
- result
45
132
  end
133
+ alias nav list_item
46
134
  end
47
135
  end
@@ -1,23 +1,61 @@
1
1
  module Storefront
2
2
  module LocaleHelper
3
- # t!(:"what.summary", :scope => :"reports.titles", :model => deal)
3
+ SCOPES_WITH_NAMESPACE_AND_NESTED_MODEL = [
4
+ '%{namespace}.%{model}.%{nested_model}.%{action}.%{attribute}',
5
+ '%{model}.%{nested_model}.%{action}.%{attribute}',
6
+ '%{namespace}.%{model}.%{action}.%{attribute}',
7
+ '%{model}.%{action}.%{attribute}',
8
+ '%{namespace}.%{model}.%{nested_model}.%{attribute}',
9
+ '%{model}.%{nested_model}.%{attribute}',
10
+ '%{namespace}.%{model}.%{attribute}',
11
+ '%{model}.%{attribute}',
12
+ '%{namespace}.%{nested_model}.%{attribute}',
13
+ '%{nested_model}.%{attribute}',
14
+ '%{namespace}.%{attribute}',
15
+ '%{attribute}'
16
+ ]
17
+
18
+ SCOPES_WITH_NESTED_MODEL = [
19
+ '%{model}.%{nested_model}.%{action}.%{attribute}',
20
+ '%{model}.%{action}.%{attribute}',
21
+ '%{model}.%{nested_model}.%{attribute}',
22
+ '%{model}.%{attribute}',
23
+ '%{nested_model}.%{attribute}',
24
+ '%{attribute}'
25
+ ]
26
+
27
+ SCOPES_WITH_NAMESPACE = [
28
+ '%{namespace}.%{model}.%{action}.%{attribute}',
29
+ '%{namespace}.%{model}.%{attribute}',
30
+ '%{model}.%{action}.%{attribute}',
31
+ '%{model}.%{attribute}',
32
+ '%{namespace}.%{attribute}',
33
+ '%{attribute}'
34
+ ]
35
+
36
+ SCOPES = [
37
+ '%{model}.%{action}.%{attribute}',
38
+ '%{model}.%{attribute}',
39
+ '%{attribute}'
40
+ ]
41
+
42
+ # t?(:"what.summary", :scope => :"reports.titles", :model => deal)
4
43
  def t?(key, options = {})
5
- return key if key.is_a?(::String)
6
- model_names = options[:model_names]
7
- model_names ||= options[:model].present? ? options[:model].class.ancestor_classes.map { |i| i.name.underscore } : []
8
- allow_blank = options.delete(:allow_blank) == true
9
-
10
- keys = [key.to_s]
11
- if options[:try].present?
12
- keys += Array(options[:default]).map do |extra_key|
13
- "#{key}.#{extra_key}"
14
- end
15
- end
44
+ return key if key.is_a?(::String) || key.blank?
16
45
 
46
+ models = Storefront::ModelProxy.model_names(options[:model] || options[:models] || options[:model_names] || storefront_config.current_scope[:resource] || [])
47
+ models << "" if models.blank?
48
+ namespaces = Array(options[:namespaces] || options[:namespace] || storefront_config.current_scope[:namespace])
49
+ namespaces << "" if namespaces.blank? && !!storefront_config.localize_with_namespace
50
+ action_name = options[:action] || storefront_config.current_scope[:action]
51
+ defaults = []
52
+ allow_blank = options.delete(:allow_blank) == true
17
53
  count = options.delete(:count)
18
54
  # none, one, many, other
19
55
  count_key = count != 1 ? :other : :one
20
56
 
57
+ keys = [key.to_s]
58
+
21
59
  if options.has_key?(:present) || options.has_key?(:past) || options.has_key?(:future)
22
60
  if options[:future] == true
23
61
  tense_key = :future
@@ -28,21 +66,53 @@ module Storefront
28
66
  tense_key = nil
29
67
  end
30
68
 
31
- defaults = []
69
+ if options.has_key?(:nested_model)
70
+ with_nested_model = !!options[:nested_model]
71
+ else
72
+ with_nested_model = !!storefront_config.localize_with_nested_model
73
+ end
32
74
 
33
- keys.each do |key|
34
- model_names.each do |model_name|
35
- path = '{{model}}.{{key}}'
36
- path.gsub!('{{model}}', model_name)
37
- path.gsub!('{{key}}', key)
38
- path.gsub!('..', '.')
39
- defaults << path
40
- end
75
+ if options.has_key?(:namespace)
76
+ with_namespace = !!options[:namespace]
77
+ else
78
+ with_namespace = !!storefront_config.localize_with_namespace
79
+ end
41
80
 
42
- path = '{{key}}'
43
- path.gsub!('{{key}}', key)
44
- path.gsub!('..', '.')
45
- defaults << path
81
+ if with_nested_model && with_namespace
82
+ # TODO, need to performance test before we do this many operations
83
+ SCOPES_WITH_NAMESPACE_AND_NESTED_MODEL
84
+ elsif with_nested_model
85
+ # TODO
86
+ SCOPES_WITH_NESTED_MODEL
87
+ elsif with_namespace
88
+ namespaces.each do |namespace|
89
+ models.each do |model|
90
+ keys.each do |_key|
91
+ SCOPES_WITH_NAMESPACE.each do |path|
92
+ path = path.dup
93
+ path.gsub!('%{namespace}', namespace)
94
+ path.gsub!('%{model}', model)
95
+ path.gsub!('%{action}', action_name)
96
+ path.gsub!('%{attribute}', _key)
97
+ path.gsub!('..', '.')
98
+ defaults << path
99
+ end
100
+ end
101
+ end
102
+ end
103
+ else
104
+ models.each do |model|
105
+ keys.each do |_key|
106
+ SCOPES.each do |path|
107
+ path = path.dup
108
+ path.gsub!('%{model}', model)
109
+ path.gsub!('%{action}', action_name)
110
+ path.gsub!('%{attribute}', _key)
111
+ path.gsub!('..', '.')
112
+ defaults << path
113
+ end
114
+ end
115
+ end
46
116
  end
47
117
 
48
118
  defaults.map!(&:to_sym)
@@ -146,9 +216,9 @@ module Storefront
146
216
  title = object[:title] || object[:label]
147
217
  subtitle = object[:subtitle]
148
218
 
149
- title = t!(:"#{key}", options.merge(:try => :title))
219
+ title = t?(:"#{key}", options.merge(:try => :title))
150
220
  title = key.to_s.split(".").last.titleize if title.blank? || title.is_a?(::Hash)
151
- subtitle = t!(:"#{key}.subtitle", options.merge(:allow_blank => true))
221
+ subtitle = t?(:"#{key}.subtitle", options.merge(:allow_blank => true))
152
222
 
153
223
  # everything has to have a title
154
224
  result[:title] = title
@@ -156,7 +226,7 @@ module Storefront
156
226
  # not everything has to have a subtitle
157
227
  result[:subtitle] = subtitle if subtitle.present?
158
228
 
159
- # it's a leaf if we're at this point!
229
+ # it's a leaf if we're at this point?
160
230
  if object.has_key?(:value)
161
231
  result[:value] = object[:value]
162
232
  else