I use rails 3. Is there any easy way to tell I18n to respect 'html safness' of string used in interpolation and make all translated string html safe by default? So if I have this en.yml:
en:
user_with_name: 'User with name <em>%{name}</em>'
and I use t('user_with_name', :name => #user.name), I get users name html escaped, but <em> and </em> is left as is?
http://guides.rubyonrails.org/i18n.html#using-safe-html-translations
The official Rails guide says you can use the interpolated variables without concern, since they are html escaped automatically, unless you specifically declare them to be String.html_safe.
From the guide:
Interpolation escapes as needed though. For example, given:
en:
welcome_html: "<b>Welcome %{username}!</b>"
you can safely pass the username as set by the user:
<%# This is safe, it is going to be escaped if needed. %>
<%= t('welcome_html', username: #current_user.username %>
Safe strings on the other hand are interpolated verbatim.
Change the name from user_with_name to user_with_name_html, then rails will know you have included html in the text.
Old question, but if someone wants to achieve this, here's the monkey patch I came up with :
module ActionView
module Helpers
module TranslationHelper
private
def html_safe_translation_key?(key)
true
end
end
end
end
Put this in an initializers and that's it!
Works with Rails 3.2.6.
Only marks the text in localization files as safe, not the interpolation parameters.
Related
In my Rails 3.1 app, I have a text field for comments and I want to be able to allow people to include clickable links (instead of just the url showing as plain text), as well as having the text field recognize when a user had line breaks in their text field (without the user adding html). How can I do this?
This works for showing a link if a user puts the html for a href:
<%= simple_format(#user.description) %>
And this works for recognizing and displaying the line breaks from carriage returns in the text_field:
<%= h(#user.description).gsub(/\n/, '<br/>').html_safe %>
However, I haven't figured out how to do both, together.
How about this?
#Doesnt work in this case
#<%= simple_format( h(#user.description).gsub(/\n/, '<br/>') ).html_safe %>
EDIT:
Seems like you need auto_link function to achieve this. Though it is removed from rails 3.1 it is available as a gem. So if you are using rails 3.1 or later you need to get this from a separate gem
#in Gemfile
gem "rails_autolink", "~> 1.0.9"
#in application.rb
require 'rails_autolink'
#Run
bundle install
#now in you view use it like
<%= h auto_link(simple_format(text)) %>
auto_link not only converts urls but also email addresses in clickable link. Get the document here.
Reference Links:
http://rubygems.org/gems/rails_autolink
http://apidock.com/rails/ActionView/Helpers/TextHelper/auto_link
Use the Rinku Gem
Link is here.
It brilliantly solves the problem. Enjoy!
I'm running into an issue with the rails auto-escaping. It currently thinks a string is html_safe (which it is), but for display purposes I need it to still escape the html. Here's the steps the string is taking.
my_string = render(:partial => "set_string", :locals => {:item => #item})
<%= my_string %>
and the partial is basically
<h2>Page Header</h2>
<strong><%= item.name %></strong>
<%= item.body %>
etc
My understanding is that because I'm displaying text in a view directly (the h2, etc) it assumes it is safe, and it also properly escapes the item outputs, which makes the whole my_string safe. So, when I try to display it with the
<%= my_string %>
It doesn't escape the remaining html. I tried adding h to force the escaping but that didn't work.
So my question is, is there anyway to force html escaping of a safe string other than calling something on the string that will make it unsafe?
Thanks a lot for your help.
Escape from ActiveSupport::SafeBuffer in Rails 3+
In this instance <%= my_string.to_str %> will double-escape as required.
SafeBuffer workings
When a string is escaped by Rails you get an ActiveSupport::SafeBuffer. From that point, extra escaping is skipped because the SafeBuffer is html_safe?. It's a clever solution! There are times though, that we wish to escape such cleverness.
Why double-escape?
I needed to re-escape content generated by tag helpers to pass generated markup to data- attributes. This has also come in handy for displaying template-generated code.
Force-escape for a String that's html_safe?
Call to_str on the SafeBuffer, which returns a String.
# Example html safe content
content = content_tag :code, 'codez<>'
content.html_safe? # true
# call .to_str
escaped = content.to_str
escaped.html_safe? # false
# The escaped String will now be re-escaped when used in a template
The to_s gotcha
The to_s method looks very much like the to_str method.
Don't use to_s here, ActionView::SafeBuffer#to_s just returns self, where to_str is called above the SafeBuffer context, returning a naturally unsafe String.
Thanks to Sebastien for the suggestion, I wanted to get the real answer here and not buried in the comments:
I looks like this works:
<%= raw CGI::escapeHTML(my_string) %>
You need the "raw" call otherwise the escapeHTML makes the string unsafe in addition to escaping it so the auto escape double escapes it.
To interpret the html (it's what i understood you need), you have to use :
<%= raw my_string %>
I am using Haml in a Ruby on Rails project. I know you use the = sign to execute Ruby, but so far what I have seen is that the Ruby code has to be the last part of a line.
I am trying to add a class to a th element dynamically. (In case it's relevant: each td also contains more Ruby.)
I have the following code:
%th= link_to 'Name', res_path
I want to add a class to th, and the name of this class is in an instance variable called class_name. I tried this:
%th.=#class_name
But it doesn't work.
How should one include Ruby code twice on the same line using Haml?
The html_options solution offered by Alok will add the class to the 'a' tag. I would do this over two lines instead of one:
%th{ :class => #class_name }
= link_to 'Name', res_path
As #DavB pointed out, only static text can be used with the ./# notation. Otherwise, you can either pass your options to your helper method (if it accepts them), or, more universally, use a hash attribute as in %th{:class => #name}. It will result in <th class="namevalue">.
You could use the html_options of the link_to tag and then add the class there. I think thats the standard way of doing this.
How can I disable automatic conversion of HTML tags in Rails3? I have output in some controller view. For example I have method which outputs simple HTML link set..
[:en, :de].map{ |locale| link_to locate.to_s.upcase , { :locale => locate } ...
In view I'm calling my method <%= my_method %>
As a result I get this:
| <a href="/login?class=language_selected&locale=en">EN</a>
How can I disable it?
I haven't worked with Rails3 so no guarantees. but it looks like this has to do with the fact that your method returns a list.
Rails will usually format internal data structures for output by escaping the special characters and displaying the html escaped interpretation of your data.
Try tacking a .join onto the end of your map call to return a string
[:en, :de].map{ |locale|
link_to locate.to_s.upcase , { :locale => locate }
...
}.join("<br/>")
Also rwilliams aka r-dub's suggestion to use raw will probably be necessary addition to this code. raw on a list however may give you an undesirable result probably because of an internal to_string call. Which is an implicit join(""). So add the raw to the method call in addition to returning a string.
<%= raw my_method %>
If you're sure your methods output is safe then you can use the raw method.
<%= raw my_method %>
I have a description text field in my Model.
No I want to add this description on the show page.
But the text renders ugly because of no linebreaks.
If i replace them with <br/> then the rails escape them with.
So i tried to use the raw() method.
I want to escape bad HTML but have the linebreaks in my output.
I end up with some ugly code.
raw(h(#place.description.gsub("\n","#linebreak#")).gsub("#linebreak#","<br/>"))
Do you have any suggestions?
you should use the simple_format helper:
<%= simple_format #place.description %>
http://api.rubyonrails.org/classes/ActionView/Helpers/TextHelper.html#method-i-simple_format
3 years later, but it's never too late to provide a good working solution
This will escape all HTML chars but the newlines (compatible Linux, Windows and Mac)
html_escape(#place.description).gsub(/(?:\n\r?|\r\n?)/, '<br />').html_safe
is what you are looking for
#place.description.html_safe.gsub("\n", '<br/>')
? But on second thought, doesn't the html_safe usage like that make it easy for the site to get XSS attack? (because it assumes the description is safe).
So won't a better solution be
<%= (h #place.description).gsub("\n", '<br/>') %>
at first I thought
<%= (h #place.description).gsub("\n", '<br/>'.html_safe) %>
is needed but actually both versions work. I then tested by adding some HTML tags to description and it got escaped into < etc, so it does prevent XSS attack.
Here's a solution that works:
<%= sanitize(#place.description.gsub("\n", "<br />"), :tags => %w(br), :attributes => %w()) %>
More reading:
Parsing newline characters in textareas without allowing all html tags
Documentation:
http://api.rubyonrails.org/classes/ActionView/Helpers/SanitizeHelper.html
From sanitize:
This sanitize helper will html encode all tags and strip all attributes that aren’t specifically allowed.
It also strips href/src tags with invalid protocols, like javascript: especially. It does its best to counter any tricks that hackers may use, like throwing in unicode/ascii/hex values to get past the javascript: filters. Check out the extensive test suite.
You can specify allowed tags with :tags option, and attributes with :attributes option.