Chris
Chris

Reputation: 1660

Rails - how to determine original controller and action when 'render' is called?

I am starting a project, and plan on keeping strings separated out by using the en.yml file. I am keeping strings organised by controller and action, i.e:

en:
  users:
    new:
      title:                       "Sign up"
      email_label:                 "E-mail address:"
      password_label:              "Password:"
      password_confirmation_label: "Password confirmation:"
      submit:                      "Sign up"

I was hoping to write a method that works out where it's being called from so that I could just call s("email_label") instead of t("users.new.email_label"):

def s(str, locals{})
  t("#{params[:controller]}.#{params[:action]}.#{str}", locals)
end

This works great for the users/new page, however when processing the 'create' action, it calls render 'new' inside this if it fails. The re-rendered page will then look for strings in 'users.create' instead of 'users.new'.

Is there a way to fix this without overriding the params[:action] value, or manually setting variables at the top of each view?

Thanks in advance

Upvotes: 0

Views: 143

Answers (1)

numbers1311407
numbers1311407

Reputation: 34072

Not an answer to the original question, but perhaps an alternative?

Why not just have translations for :new_title, :edit_title, and so on, then call them explicitly?

Doing it by action probably isn't correct, as demonstrated by the issue you're having. You're not looking for translation based on action, but really by template. And even that is probably situational. Also, would there ever even be template translations for update or create? Probably not, as they don't render templates (your issue).

Plus, what if you later wanted to have a form to create a record on a different page? E.g. a "new comment" form on a "posts" page handled by the posts controller. Things could get hairy.

It seems like you'd gain more control by providing translations for the keys you know will exist, and calling them explicitly.

# translations
en:
  users:
    new_title: Sign Up
    edit_title: Edit User
    index_title: Users

# new.html.erb (and so on)
<%= title s(:new_title) %>
...

# controller helper method
def s(key, locals = {})
  I18n.t key, locals.merge(:scope => controller_name)
end

Additionally, you may know this already, but the label helpers have i18n baked in using model translations, which may help to avoid repetitive definitions. These will also be the translations used for attribute names in generated errors. E.g.

en:
  attributes:
    # globally defined attribute translations
    password: Password

  activerecord:
    attributes:
      user:
        # per model overrides
        password: User Password

# The label helpers then use these (this label would translate to "User Password")
= form_for(@user) do |f|
  = f.label :password 

There are also dynamic translations for button helpers, based on whether or not the record is persisted. Depending on how you're handling sign ups, this may or may not work cleanly out of the box. If your sign up is just creating Users, though, it should.

en:
  helpers:
    user:
      create: "Sign Up Now!"
      update: "Update User!"

# This label would translate to "Sign Up Now!"
= form_for(User.new) do |f|
  = f.submit

Upvotes: 1

Related Questions