Page title helper

Ever wondered if there was an easier and DRY-way to set your page titles (and/or headings), introducing page title helper, a small Rails 3 view helper to inflect titles from controllers & actions.

Note: for Rails 2.x please use version 1.0.1: gem install page_title_helper -v 1.0.1, because the latest versions are no longer compatible with Rails 2.x.

In your layout add this to your <head>-section:

  ...
  <title><%= page_title %></title>
  ...

That's it. Now just add translations, in e.g. config/locales/en.yml:

  en:
    contacts:
      index:
        title: "Contacts"

When /contacs/ is requested, the key :en, :contacts, :index, :title is looked up and printed, together with the applications basename, like: Contacts - My cool App. The format etc. is of course configurable, just head down to the options.

Installation

As gem (from rubygems.org):

# then add the following line to Gemfile
gem 'page_title_helper'

# living on the bleeding edge?
gem 'page_title_helper', :git => 'git://github.com/lwe/page_title_helper.git'

or as plain old Rails plugin:

rails plugin install git://github.com/lwe/page_title_helper.git

Translated titles

All translated titles are inflected from the current controller and action, so to easily explain all lookups, here an example with the corresponding lookups:

Admin::AccountController#index => :'admin.account.index.title'
                                  :admin.account.title'
                                  options[:default]

For create and update a further fallback to new.title and edit.title have been added, because they certainly are duplicates.

Customize titles

Need a custom title, or need to fill in some placeholders? Just use the bang method (page_title!), in e.g. contacts/show.html.erb the requirement is to display the contacts name in the <title>-tagas well as in the heading?

<h1><%= page_title!(@contact.name) %></h1>

A call to page_title will now return the contacts name, neat :) if for example the <h1> does not match the <title>, then well, just do something like:

<% page_title!(@contact.name + " (" + @contact.company.name + ")") %>
<h1><%= @contact.name %></h1>

Guess, that's it. Of course it's also possible to use translate within page_title!, to translate custom titles, like:

# in config/locales/en.yml:
en:
  dashboard:
    index:
      title: "Welcome back, {{name}}"

# in app/views/dashboard/index.html.erb:
<h1><%= page_title!(t('.title', :name => @user.first_name)) %></h1>

More fun with :format

The :format option is used to specify how a title is formatted, i.e. if the app name is prependor appended, or if it contains the account name etc. It uses a similar approach as paperclip's path interpolations:

page_title :format => ':title / :app' # => "Contacts / My cool app"

Adding custom interpolations is as easy as defining a block, for example to access the current controller:

PageTitleHelper.interpolates :controller do |env|
  env[:view].controller.controller_name.humanize
end

page_title :format => ':title / :controller / :app' # => "Welcome back / Dashboard / My cool app"

To access just the title, without any magic app stuff interpolated or appended, use:

page_title! "untitled"
page_title :format => false # => "untitled"

Need a custom format for a single title? Just return an array:

# in the view:
<h1><%= page_title!(@contact.name, ":title from :company - :app") %></h1> # => <h1>Franz Meyer</h1>

# in the <head>
<title><%= page_title %></title> # => this time it will use custom title like "Franz Meyer from ABC Corp. - My cool app"

To streamline that feature a bit and simplify reuse of often used formats, it's possible to define format aliases like:

# in an initializer, e.g. config/initializers/page_title_helper.rb:
PageTitleHelper.formats[:with_company] = ":title from :company - :app"
PageTitleHelper.formats[:promo] = ":app - :title" # show app first for promo pages :)

# then in the view to display a contact...
page_title! @contact.name, :with_company

# ...or for the promo page via config/locales/en.yml (!)
en:
  pages:
    features:
      title:
        - "Features comparison"
        - !ruby/sym promo

Pretty, cool, aint it? The special :format => :app works also via the formats hash. Then there is also a :default format, which can be used to override the default format.

All options - explained

OptionDescriptionDefaultValues
:app Specify the applications name, however it's recommended to define it via translation key :'app.name'. Inflected from Rails.root string
:default String which is displayed when no translation exists and no custom title has been specified. Can also be set to a symbol or array to take advantage of I18n.translates :default option. :'app.tagline' string, symbol or array of those
:format Defines the output format, accepts a string containing multiple interpolations, or a symbol to a format alias, see More fun with :format. If set to +false+, just the current title is returned. :default string, symbol

Options can be set globally via PageTitleHelper.options. Note, currently it only makes sense to set :default globally.

To add or change formats use:

# change the default format used (if no format is specified):
PageTitleHelper.formats[:default] = ":title // :app"

# add a custom format alias (which can be used with page_title(:format => :promo))
PageTitleHelper.formats[:promo] = ":app // :title"

Note: it's recommended to add this kind of stuff to an initializer, like e.g. config/initializers/page_title_helper.rb.

A (maybe useful) interpolation

The internationalized controller name, with fallback to just display the humanized name:

PageTitleHelper.interpolates :controller do |env|
  c = env[:view].controller
  I18n.t(c.controller_path.tr('/', '.') + '.controller', :default => c.controller_name.humanize)
end

Note: Put this kind of stuff into an initializer, like config/initializers/page_title_helper.rb or someting like that.

Licence and copyright

Copyright (c) 2009 Lukas Westermann (Zurich, Switzerland), released under the MIT license