Active Record, Migration, and Translation

Hi,

I think the columns and table in migration should be able to have an
optional “display_name” set manually. Something like:

create_table :people, {display_name => “Personne”} do |t|
t.column :first_name :string, :display_name => “Prénom”.
end

Let me explain my point of view:

Rails is a framework made to write programs in English. You see it when
you are confronted to the pluralization rules, or the _confirmation
fields.
I think this is okay, because programming Rails without speaking English
is a pain anyway: most of the docs and tutorial available on the web are
in English, and all functions have english name.

But where I think Rails goes a little bit too far, is that it is also
meant to be a lot more easy using it to write application with english
output, for English-speaking user. And if programmers are writing for
non-English user, it’s a lot more pain for them. I think this is not
fair. World is not just english-speaking, and Rails is a world-wide open
software.

And I think it would not be difficult for Rails to make it easy
programming a non-english output.

For the translations of the error messages, I found that
localisation_simplified is a very nice and very lightweight plugin that
should be integrated in Rails by default. This would spare programmers
the pain to check all plugins availables at
http://wiki.rubyonrails.org/rails/pages/InternationalizationComparison
when they only want one language output, but non-english.

But this plugin does not offer a solution to translate the database
fields, so generated scafold is all in english, and I have to correct
all the rhtml files manually
Moreover, I’m still displaying error messages like:
“First name est un champs obligatoire.”
So I have to write all error messages manually, repeating myself a lot.
Using gettext or internationalisation plugin to solve this problem makes
me feel like taking a hammer to kill a bee: I just want one language
output.

Scaffolding is such a good part of rails, that it should also be fully
enjoyable for programmers wanting a non-english-output!

To solve this, my first thought was to write my database in my target
language (French). But then I was confronted to the pluralization
problem, and the “_confirmation” things. Moreover, all functions of the
framework are in English. So when I’m writing something like
“utilisateur.create”, I find it ugly, and I feel like neither English
nor French programmer would understand what I meant when I wrote this.
As I said, Rails is meant to be programmed in full-english.

So if I write my database in English, and want the user to see it in
french, then I have to put the translation somewhere. And if I change or
create or delete a field in my database, I also have to change, create
or delete the translation. (and I don’t want to repeat myself).

This is why I think the best place for translation is in migration: this
is where we are defining what will be the name of the fields in the
database, so it’s the best place to define the name we want it to be
displayed in the app.

The perfect thing would be just one more option, available for every
kind of fields:

create_table :people, {display_name => “Personne”} do |t|
t.column :first_name :string, :display_name => “Prénom”.
end

If default scaffold behaviour is able to understand this, we’re done.
This feature would also be very useful to people with ugly existing
database that they’re just not allowed to touch.

And this would also help for globalisation: I would then be able to
write:
t.column :first_name :string, display_name => translate(“First Name”).

And if you don’t give a display name, you’ve just got the default
behaviour with the “humanize” thing.

I know this is not very compatible with the “sexy migration” of rails
2.0, but I think there is a lot of people for who this feature would be
more useful than the “sexy migration” one.

Hope I conviced someone able to do this!

Sebastien.

on a related note, I’d like to be able to display a more friendly
filed name than the table column in the form validation error message.
i.e., I want to say

validates_format_of :column_name
:with => /^[a-z0-9 ]*$/i,
:message => ‘friendly name should be keywords separated by spaces.
Keywords should be letters and numbers only’

but I end up with the column_name stuck in front of the message. is
there a workaround (renaming the column isn’t an option.)

To change the error messages, you can use override the fuction
“errormessage” as shown below. Place a file containing the new code in
the “lib” directory.
Then require this file in your config/environment.rb
(ie, if your file is named "my_custem_error_message.rb’, put require
‘my_custom_error_message_file’ in config/environment.rb)
Here I give you the code used by the “localisation_simplified” plugin,
you can change it to fill your special needs.

module ActionView
module Helpers

 #Modify ActiveRecord to use error message headers (text from 

lang-file)
module ActiveRecordHelper
alias_method :old_error_messages_for, :error_messages_for

   def error_messages_for(*params)
     options = params.last.is_a?(Hash) ? params.pop.symbolize_keys : 

{}
objects = params.collect {|object_name|
instance_variable_get("@#{object_name}") }.compact
count = objects.inject(0) {|sum, object| sum +
object.errors.count }
unless count.zero?
html = {}
[:id, :class].each do |key|
if options.include?(key)
value = options[key]
html[key] = value unless value.blank?
else
html[key] = ‘errorExplanation’
end
end
messages = ActiveRecord:: Errors.default_error_messages
if options[:action]
header_message = pluralize(count,
messages[:error_forbid])+’ '+options[:action]
else
header_message = format( messages[:error_header],
pluralize(count, messages[:error_translation]),
(options[:object_name] ||
params.first).to_s.gsub("_", " "))
end
error_messages = objects.map {|object|
object.errors.full_messages.map {|msg|content_tag(:li, msg) } }
content_tag(:div,
content_tag(options[:header_tag] || :h2, header_message) <<
content_tag(:p, messages[:error_subheader]) <<
content_tag(:ul, error_messages),
html
)
else
‘’
end
end
end
end
rubynuby a écrit :

Frederick C. a écrit :

Keywords should be letters and numbers only’

end
end
end

This is what I’m doing, but I wrote my message to say there should be a
better way: I have to write two times the attribute name: one for column
definition, one for translation definition. So if it changes I have to
correct it two times also.

On 5 Dec 2007, at 13:27, rubynuby wrote:

on a related note, I’d like to be able to display a more friendly
filed name than the table column in the form validation error message.
i.e., I want to say

validates_format_of :column_name
:with => /^[a-z0-9 ]*$/i,
:message => ‘friendly name should be keywords separated by spaces.
Keywords should be letters and numbers only’

Well looking in validations.rb, it looks like full_error_messages uses
calls human_attribute_name. By default this just does things like
convert first_name to First name, but you could imagine something like

class Person < AR::Base
def self.human_attribute_name(attr_name)
case attr_name
when ‘first_name’ then ‘Prénom’

end
end
end

On 8 Dec 2007, at 21:29, Sébastien Lamy wrote:

validates_format_of :column_name

be a
better way: I have to write two times the attribute name: one for
column
definition, one for translation definition. So if it changes I have to
correct it two times also.

I don’t think it can be in the migration (how’s the model going to
know at runtime?), but overwriting human_name is a chore.
If you could write

class Person < AR::Base
display :first_name, :as => ‘Prénom’
end

Then it would be less tedious.

Fred