getting access to uninterpolated/untranslated strings

71 views
Skip to first unread message

Erkki Eilonen

unread,
Oct 9, 2008, 8:12:03 AM10/9/08
to rails-i18n
Hey there,

Yesterday I started out with a need to use "nice" validation messages
in active record:

class Person < ActiveRecord::Base
validates_presence_of :first_name
end

The default validation would be "First name can't be blank",
I'd like to use "Please input your First name". This is currently
impossible
(without using errors.add_to_base) since
ActiveRecord::Errors#full_messages
always prefixes the custom error message with the attribute name
(though one might argue that ActiveRecord::Errors#full_messages should
be customized anw).

To fix this I tried to make ActiveRecord::Errors#full_messages smarter
by introspecting the error message and not prefixing the message
with the attribute name when the message already includes the
attribute,
something like this: http://pastie.org/288102.txt (notice the
erroneous use of
calling translate multiple times).

After this I thought that maybe I18n.backend#lookup should be a part
of the public api for backends.
Tarmo Tänav (tarmo_t) talked to Sven Fuchs about this and they
figured
perhaps I18n.translate should take an extra option, :context => true
and
then return a 'Translation' object with extra context info applied
(the uninterpolated string, etc).
The 'Translation' object could only be returned with :context => true
to make things less bloated
in other cases.

Does anyone have any thoughts/recommendations/suggestions/objections?

Sven Fuchs

unread,
Oct 25, 2008, 6:17:22 AM10/25/08
to rails...@googlegroups.com
Hi Erkki,

sorry I haven't been able to come back to you earlier. I would have
expected that this would raise quite some discussion on this list
because there was some interest in better error messages in the past.

Folks,

the gist of the problem is that ActiveRecord#full_messages always puts
the attribute name in front of your custom error messages. That of
course does not make sense when the custom message already contains
the attribute name as an interpolated value (as in "Please input your
{{first_name}}").

In order to fix that Rails needs to know if the first_name value was
interpolated to the translation or not.

I can think of three approaches to that:

1. make #lookup public

http://pastie.org/288102 adds an error_message object with
an :uninterpolated_error_message attr_accessor and populates it with
call to #lookup. In order to make this solid we'd need to expose
#lookup in the public API.

2. check for the attribute translation in the error message

Similiar to the pastie above one could check if the translated error
message contains the translated attribute name. Roughly like:

class ErrorMessage < String
def initialize(attr_name); @attr_name = attr_name; end
def attr_name_interpolated?; self.include?(@attr_name); end
end

3. allow the API to return translation meta data

This is what we've done in Globalize2, see [1] and [2]. Instead of
returning a Ruby String from the backend we return a Translation
object (that extends String) and populate it with some interesting
meta data.

Of course doing something like this in Rails would adds additional
memory consumption even for people who are not interested in I18n at
all. Custom ActiveRecord error translations used in #full_messages
seems to be a pretty special case so it might be a waste to return all
the meta data all the time.

So maybe this is the root of the idea to have I18n.translate take
another option like :context => true or :_meta=> true or so and only
return Translation objects if it is true.


I'm still not quite sure about this. Mostly I feel that this is a
special case where we could go with a rather simple solution like 2)
even though it's not perfect. Would keep the Simple backend simple.

Otoh I'm not sure about what happens or is planned to happen in Rails
regarding the whole error message stuff at all. I've heard here and
there that people think it sux and should be replaced but I'm not into
it enough to even know whom to ask about it.


So, what do you all think? :)



[1] http://github.com/joshmh/globalize2/tree/master/lib/globalize/translation.rb
[2] http://github.com/joshmh/globalize2/tree/master/lib/globalize/backend/static.rb

Yaroslav Markin

unread,
Oct 25, 2008, 6:22:31 AM10/25/08
to rails...@googlegroups.com
On Sat, Oct 25, 2008 at 2:17 PM, Sven Fuchs <sven...@artweb-design.de> wrote:

the gist of the problem is that ActiveRecord#full_messages always puts
the attribute name in front of your custom error messages. That of
course does not make sense when the custom message already contains
the attribute name as an interpolated value (as in "Please input your
{{first_name}}").

A quick and somewhat dirty fix to this was introduced about two years ago:


I have to say this hack still works and this is what I use right now with I18n.

Regarding a better solution.. I think we need to have a key on validate_* classmacros, or, even better, cooperate on removing error_messages_for/full_messages from Rails.

--
Yaroslav Markin

Reply all
Reply to author
Forward
0 new messages