ryanb / nifty-generators

A collection of useful Rails generator scripts.
MIT License
1.98k stars 283 forks source link

Model translation in the message header #93

Open belgoros opened 13 years ago

belgoros commented 13 years ago

I used nifty-geberators gem on before-3.0* Rails version, all the translations worked fine. After passing to Rails 3.0.5, nifty-generators 0.4.5, i18n 0.5.0, Ruby 1.9.2p180, I can't figure out how to achive the translation of error meassage header wher the name of the model should be translated. Without using the nifty-generators gem, I solved it as follows in my view:

<%= form_for(@user) do |f| %>
<% if @user.errors.any? %>
<div id="error_explanation">      
  <h2><%= t('errors.template.header', :model=> @user.class.human_name, :count=> @user.errors.count) %></h2>

  <ul>
  <% @user.errors.full_messages.each do |msg| %>
    <li><%= msg %></li>
  <% end %>
  </ul>
</div>
<% end %>

I changed nothing in the translation YAML file downloaded from Github https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale except adding some model-specific translation and its attributes. How can i modify the 'error_messages_helper.rb' file or what to pass from the view to solve the problem? Thanks.

belgoros commented 13 years ago

Hi, Ryan!

I fixed the headr translation as follows for the moment:

#in a form partial, for example
<%= form_for @user do |f| %>
  <%= f.error_messages(:header_message => t('errors.template.header', :model=> @user.class.model_name.human, :count=> @user.errors.count), :message => t('errors.template.body')) %>
  <p>
    <%= f.label t 'activerecord.attributes.user.firstname' %><br />
    <%= f.text_field :firstname %>
  </p>
  <p>
    <%= f.label t 'activerecord.attributes.user.lastname' %><br />
    <%= f.text_field :lastname %>
  </p>
  <p><%= f.submit %></p>
<% end %>

what means that I have to use the same tecnhic to pass parameter from the view to the translation file as I did in any other RoR application that doen't use nifty_generators gem. May be it is not DRY enough. Would it be better to modify directly the ErrorMessages helper ? Thanks & regards

ryanb commented 13 years ago

The helper in NiftyGenerators has a translation like this: activerecord.errors.header and activerecord.errors.message so you'll need to adjust those in your en.yml file. Does setting those translations work?

So what your'e showing here is the previous translation keys Rails 2 used? Maybe they should be changed to match that.

belgoros commented 13 years ago

In yml translation file that I downloaded from https://github.com/svenfuchs/rails-i18n/tree/master/rails/locale, there is no more activerecord.errors.header but errors.template.header instead. The 'activerecord' tree is defined as follows:


activerecord:
    models:
      user: "Utilisateur"
    attributes:
      user:  
        firstname: "Prénom"
        lastname: "Nom"  
    errors:
      messages:
        taken: "n'est pas disponible"
        record_invalid: "La validation a échoué : %{errors}"
        <<: *errors_messages
      template:
        <<: *errors_template
      full_messages:
        format: "%{attribute} %{message}"
and 'errors' tree is defined as follows:

errors:
    format: "%{attribute} %{message}"
    messages: &errors_messages
      inclusion: "n'est pas inclus(e) dans la liste"
      exclusion: "n'est pas disponible"
      invalid: "n'est pas valide"
      confirmation: "ne concorde pas avec la confirmation"
      accepted: "doit être accepté(e)"
      empty: "doit être rempli(e)"
      blank: "doit être rempli(e)"
      too_long: "est trop long (pas plus de %{count} caractères)"
      too_short: "est trop court (au moins %{count} caractères)"
      wrong_length: "ne fait pas la bonne longueur (doit comporter %{count} caractères)"
      not_a_number: "n'est pas un nombre"
      not_an_integer: "doit être un nombre entier"
      greater_than: "doit être supérieur à %{count}"
      greater_than_or_equal_to: "doit être supérieur ou égal à %{count}"
      equal_to: "doit être égal à %{count}"
      less_than: "doit être inférieur à %{count}"
      less_than_or_equal_to: "doit être inférieur ou égal à %{count}"
      odd: "doit être impair"
      even: "doit être pair"
    template: &errors_template
      header:
        one:   "Impossible d'enregistrer %{model} : 1 erreur"
        other: "Impossible d'enregistrer %{model} : %{count} erreurs"
      body: "Veuillez vérifier les champs suivants : "
That's why I modified the 'ErrorMessagesHelper' as follows:

module ErrorMessagesHelper
  # Render error messages for the given objects. The :message and :header_message options are allowed.
  def error_messages_for(*objects)
    options = objects.extract_options!
    error_object = objects[0]  
    options[:header_message] ||= I18n.t('errors.template.header', :model=> error_object.class.model_name.human, :count=> error_object.errors.count)
    options[:message] ||= I18n.t('errors.template.body')

# options[:header_message] ||= I18n.t(:"activerecord.errors.header", :default => "Invalid Fields")

# options[:message] ||= I18n.t(:"activerecord.errors.message", :default => "Correct the following errors and try again.")

```
messages = objects.compact.map { |o| o.errors.full_messages }.flatten
unless messages.empty?
  content_tag(:div, :class => "error_messages") do
    list_items = messages.map { |msg| content_tag(:li, msg) }
    content_tag(:h2, options[:header_message]) + content_tag(:p, options[:message]) + content_tag(:ul, list_items.join.html_safe)
  end
end
```

  end

  module FormBuilderAdditions
    def error_messages(options = {})  
      @template.error_messages_for(@object, options)
    end
  end
end

ActionView::Helpers::FormBuilder.send(:include, ErrorMessagesHelper::FormBuilderAdditions)
May be there is a better solution ?
ryanb commented 13 years ago

Hmm, so it looks like it shouldn't go under the activerecord namespace. I'll consider changing this in the nifty:layout generator.

JeanMertz commented 13 years ago

@ryanb I just wanted to place my support here for this problem, but I don't think the solution of @javix is correct.

As far as I can see, errors still go in the activerecord namespace, see: https://github.com/svenfuchs/rails-i18n/blob/master/rails/locale/en-US.yml

Some more problems I am running into with the ErrorMessagesHelper:

1) activerecord.errors.header has now been changed to activerecord.errors.template.header

2) activerecord.errors.message has been replaced by activerecord.errors.template.body

3) Model and attribute names aren't translated

This is the returned error: Users email can't be blank

While this is in my en-US.yml:

en:
  activerecord:
    models:
      user: "person"
    attributes:
      user:
        email: "e-mail"

Any thoughts on this?

JeanMertz commented 13 years ago

Actually, it seems my issues had to do with nested_forms, which is kind of weird:

The above didn't work, but this will:

  activerecord:
    attributes:
      website:
        domain: "domein"
        users:
          email: "e-mail"
          password_digest: "wachtwoord"
      user:
        email: "e-mail"
        password_digest: "wachtwoord"

    errors:
      template:
        header:
          one:    "%{model} niet opgeslagen: 1 fout gevonden"
          other:  "%{model} niet opgeslagen: %{count} fouten gevonden"
        body: "Controleer de volgende velden:"

Though I wonder if this isn't something that should be fixed/changed in Rails. It isn't exactly DRY in this case, because I have to declare the attributes again for each nested field, but I don't see any reason why a nested form field should be named different than a regular field.

edit: seems this method is soon to be deprecated, not sure if there will be some replacement for this though, see: https://github.com/rails/rails/issues/1869

ryanb commented 13 years ago

@JeanMertz thanks for looking into this issue. I hope to spend some time on it soon and find a good fix. If you do find a concrete solution feel free to submit a pull request.