diff --git a/actionview/CHANGELOG.md b/actionview/CHANGELOG.md
index 552a902349a09fea24c848a74e192eecb4727921..396249ac377caa4e58aeffff0f4d595360e3873d 100644
--- a/actionview/CHANGELOG.md
+++ b/actionview/CHANGELOG.md
@@ -1,3 +1,10 @@
+* Provide a `builder` object when using the `label` form helper in block form.
+
+ The new `builder` object responds to `translation`, allowing I18n fallback support
+ when you want to customize how a particular label is presented.
+
+ *Alex Robbin*
+
* Add I18n support for input/textarea placeholder text.
Placeholder I18n follows the same convention as `label` I18n.
diff --git a/actionview/lib/action_view/helpers/tags/label.rb b/actionview/lib/action_view/helpers/tags/label.rb
index 39b2f48c390b1000ce9e94581a428b6ae37ba900..08a23e497ed14665f17cebe8995d10711ce06f8b 100644
--- a/actionview/lib/action_view/helpers/tags/label.rb
+++ b/actionview/lib/action_view/helpers/tags/label.rb
@@ -2,6 +2,39 @@ module ActionView
module Helpers
module Tags # :nodoc:
class Label < Base # :nodoc:
+ class LabelBuilder # :nodoc:
+ attr_reader :object
+
+ def initialize(template_object, object_name, method_name, object, tag_value)
+ @template_object = template_object
+ @object_name = object_name
+ @method_name = method_name
+ @object = object
+ @tag_value = tag_value
+ end
+
+ def translation
+ method_and_value = @tag_value.present? ? "#{@method_name}.#{@tag_value}" : @method_name
+ @object_name.gsub!(/\[(.*)_attributes\]\[\d+\]/, '.\1')
+
+ if object.respond_to?(:to_model)
+ key = object.model_name.i18n_key
+ i18n_default = ["#{key}.#{method_and_value}".to_sym, ""]
+ end
+
+ i18n_default ||= ""
+ content = I18n.t("#{@object_name}.#{method_and_value}", :default => i18n_default, :scope => "helpers.label").presence
+
+ content ||= if object && object.class.respond_to?(:human_attribute_name)
+ object.class.human_attribute_name(method_and_value)
+ end
+
+ content ||= @method_name.humanize
+
+ content
+ end
+ end
+
def initialize(object_name, method_name, template_object, content_or_options = nil, options = nil)
options ||= {}
@@ -32,33 +65,24 @@ def render(&block)
options.delete("namespace")
options["for"] = name_and_id["id"] unless options.key?("for")
- if block_given?
- content = @template_object.capture(&block)
- else
- method_and_value = tag_value.present? ? "#{@method_name}.#{tag_value}" : @method_name
- content = if @content.blank?
- @object_name.gsub!(/\[(.*)_attributes\]\[\d+\]/, '.\1')
-
- if object.respond_to?(:to_model)
- key = object.model_name.i18n_key
- i18n_default = ["#{key}.#{method_and_value}".to_sym, ""]
- end
-
- i18n_default ||= ""
- I18n.t("#{@object_name}.#{method_and_value}", :default => i18n_default, :scope => "helpers.label").presence
- else
- @content.to_s
- end
-
- content ||= if object && object.class.respond_to?(:human_attribute_name)
- object.class.human_attribute_name(method_and_value)
- end
+ builder = LabelBuilder.new(@template_object, @object_name, @method_name, @object, tag_value)
- content ||= @method_name.humanize
+ content = if block_given?
+ @template_object.capture(builder, &block)
+ elsif @content.present?
+ @content.to_s
+ else
+ render_component(builder)
end
label_tag(name_and_id["id"], content, options)
end
+
+ private
+
+ def render_component(builder)
+ builder.translation
+ end
end
end
end
diff --git a/actionview/test/template/form_helper_test.rb b/actionview/test/template/form_helper_test.rb
index 69107691838962244f169b1e1a0d92f3297e8570..6f82462425c6d444881d45b8ad56f22b261da87b 100644
--- a/actionview/test/template/form_helper_test.rb
+++ b/actionview/test/template/form_helper_test.rb
@@ -319,6 +319,15 @@ def test_label_with_block_and_options
)
end
+ def test_label_with_block_and_builder
+ with_locale :label do
+ assert_dom_equal(
+ '',
+ label(:post, :body) { |b| "#{b.translation}".html_safe }
+ )
+ end
+ end
+
def test_label_with_block_in_erb
assert_equal(
%{},