aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCraig Davey <me@craigdavey.ca>2010-04-09 21:01:32 -0400
committerDavid Heinemeier Hansson <david@loudthinking.com>2010-04-13 17:35:10 -0700
commit5208cc3cf5d54720512ff50c2b97e9f4369aaa27 (patch)
treef10f4ddc330fbc71fc3b3fa7a6201026b4920f59
parent0ab2ba336f2b094a4235b54a1b17f8bef3fe3b2b (diff)
downloadrails-5208cc3cf5d54720512ff50c2b97e9f4369aaa27.tar.gz
rails-5208cc3cf5d54720512ff50c2b97e9f4369aaa27.tar.bz2
rails-5208cc3cf5d54720512ff50c2b97e9f4369aaa27.zip
Changed translate helper so that it doesn’t mark every translation as safe HTML. Only keys with a "_html" suffix and keys named "html" are considered to be safe HTML. All other translations are left untouched.
Signed-off-by: David Heinemeier Hansson <david@loudthinking.com>
-rw-r--r--actionpack/CHANGELOG5
-rw-r--r--actionpack/lib/action_view/helpers/translation_helper.rb26
-rw-r--r--actionpack/test/fixtures/test/array_translation.erb2
-rw-r--r--actionpack/test/template/translation_helper_test.rb17
4 files changed, 45 insertions, 5 deletions
diff --git a/actionpack/CHANGELOG b/actionpack/CHANGELOG
index f221661c25..388169d981 100644
--- a/actionpack/CHANGELOG
+++ b/actionpack/CHANGELOG
@@ -1,3 +1,8 @@
+*Rails 3.0.0 [beta 4/release candidate] (unreleased)*
+
+* Changed translate helper so that it doesn’t mark every translation as safe HTML. Only keys with a "_html" suffix and keys named "html" are considered to be safe HTML. All other translations are left untouched. [Craig Davey]
+
+
*Rails 3.0.0 [beta 3] (April 13th, 2010)*
* New option :as added to form_for allows to change the object name. The old <% form_for :client, @post %> becomes <% form_for @post, :as => :client %> [spastorino]
diff --git a/actionpack/lib/action_view/helpers/translation_helper.rb b/actionpack/lib/action_view/helpers/translation_helper.rb
index 457944dbb6..89c1b4a275 100644
--- a/actionpack/lib/action_view/helpers/translation_helper.rb
+++ b/actionpack/lib/action_view/helpers/translation_helper.rb
@@ -3,17 +3,28 @@ require 'action_view/helpers/tag_helper'
module ActionView
module Helpers
module TranslationHelper
- # Delegates to I18n#translate but also performs two additional functions. First, it'll catch MissingTranslationData exceptions
+ # Delegates to I18n#translate but also performs three additional functions. First, it'll catch MissingTranslationData exceptions
# and turn them into inline spans that contains the missing key, such that you can see in a view what is missing where.
#
# Second, it'll scope the key by the current partial if the key starts with a period. So if you call translate(".foo") from the
# people/index.html.erb template, you'll actually be calling I18n.translate("people.index.foo"). This makes it less repetitive
# to translate many keys within the same partials and gives you a simple framework for scoping them consistently. If you don't
# prepend the key with a period, nothing is converted.
+ #
+ # Third, it’ll mark the translation as safe HTML if the key has the suffix "_html" or the last element of the key is the word
+ # "html". For example, calling translate("footer_html") or translate("footer.html") will return a safe HTML string that won’t
+ # be escaped by other HTML helper methods. This naming convention helps to identify translations that include HTML tags so that
+ # you know what kind of output to expect when you call translate in a template.
+
def translate(key, options = {})
options[:raise] = true
translation = I18n.translate(scope_key_by_partial(key), options)
- (translation.respond_to?(:join) ? translation.join : translation).html_safe
+ translation = (translation.respond_to?(:join) ? translation.join : translation)
+ if html_safe_translation_key? key
+ translation.html_safe
+ else
+ translation
+ end
rescue I18n::MissingTranslationData => e
keys = I18n.normalize_keys(e.locale, e.key, e.options[:scope])
content_tag('span', keys.join(', '), :class => 'translation_missing')
@@ -27,7 +38,7 @@ module ActionView
alias :l :localize
private
-
+
def scope_key_by_partial(key)
strkey = key.respond_to?(:join) ? key.join : key.to_s
if strkey.first == "."
@@ -40,6 +51,15 @@ module ActionView
key
end
end
+
+ def html_safe_translation_key?(key)
+ last_key = if key.is_a? Array
+ key.last
+ else
+ key.to_s.split('.').last
+ end
+ (last_key == "html") || (last_key.ends_with? "_html")
+ end
end
end
end
diff --git a/actionpack/test/fixtures/test/array_translation.erb b/actionpack/test/fixtures/test/array_translation.erb
index 12c0763313..def3a1a0c1 100644
--- a/actionpack/test/fixtures/test/array_translation.erb
+++ b/actionpack/test/fixtures/test/array_translation.erb
@@ -1 +1 @@
-<%= t(['foo', 'bar']) %> \ No newline at end of file
+<%= t(['foo', 'bar', 'html']) %> \ No newline at end of file
diff --git a/actionpack/test/template/translation_helper_test.rb b/actionpack/test/template/translation_helper_test.rb
index 6782bf06d4..b382b5eb22 100644
--- a/actionpack/test/template/translation_helper_test.rb
+++ b/actionpack/test/template/translation_helper_test.rb
@@ -25,7 +25,7 @@ class TranslationHelperTest < ActiveSupport::TestCase
def test_translation_of_an_array_with_html
expected = '<a href="#">foo</a><a href="#">bar</a>'
- I18n.expects(:translate).with(["foo", "bar"], :raise => true).returns(['<a href="#">foo</a>', '<a href="#">bar</a>'])
+ I18n.expects(:translate).with(["foo", "bar", "html"], :raise => true).returns(['<a href="#">foo</a>', '<a href="#">bar</a>'])
@view = ActionView::Base.new(ActionController::Base.view_paths, {})
assert_equal expected, @view.render(:file => "test/array_translation")
end
@@ -47,4 +47,19 @@ class TranslationHelperTest < ActiveSupport::TestCase
@view = ActionView::Base.new(ActionController::Base.view_paths, {})
assert_equal "foobar", @view.render(:file => "test/scoped_array_translation")
end
+
+ def test_translate_does_not_mark_plain_text_as_safe_html
+ I18n.expects(:translate).with("hello", :raise => true).returns("Hello World")
+ assert_equal false, translate("hello").html_safe?
+ end
+
+ def test_translate_marks_translations_named_html_as_safe_html
+ I18n.expects(:translate).with("html", :raise => true).returns("<a>Hello World</a>")
+ assert translate("html").html_safe?
+ end
+
+ def test_translate_marks_translations_with_a_html_suffix_as_safe_html
+ I18n.expects(:translate).with("hello_html", :raise => true).returns("<a>Hello World</a>")
+ assert translate("hello_html").html_safe?
+ end
end