Permalink
Browse files

have no fear, i18n is here!

:previous_label, :next_label, page gap text and the `page_entries_info`
method output can now all be translated by overriding values seen in
"lib/will_paginate/locale/en.yml" from your own application locale files.

closes #99, #10, #109
  • Loading branch information...
1 parent db32fcf commit f1fba716bad505a52a2199bdd5e7bb4e768073f3 @mislav committed Jul 28, 2011
@@ -1,5 +1,4 @@
require 'set'
-require 'will_paginate/array'
# copied from ActiveSupport so we don't depend on it
@@ -18,33 +17,6 @@ def except!(*keys)
end
end
-unless Hash.method_defined? :slice
- Hash.class_eval do
- # Returns a new hash with only the given keys.
- def slice(*keys)
- allowed = Set.new(respond_to?(:convert_key) ? keys.map { |key| convert_key(key) } : keys)
- reject { |key,| !allowed.include?(key) }
- end
-
- # Replaces the hash with only the given keys.
- def slice!(*keys)
- replace(slice(*keys))
- end
- end
-end
-
-unless String.method_defined? :constantize
- String.class_eval do
- def constantize
- unless /\A(?:::)?([A-Z]\w*(?:::[A-Z]\w*)*)\z/ =~ self
- raise NameError, "#{self.inspect} is not a valid constant name!"
- end
-
- Object.module_eval("::#{$1}", __FILE__, __LINE__)
- end
- end
-end
-
unless String.method_defined? :underscore
String.class_eval do
def underscore
@@ -0,0 +1,19 @@
+en:
+ views:
+ will_paginate:
+ previous_label: "← Previous"
+ next_label: "Next →"
+ page_gap: "…"
+
+ page_entries_info:
+ single_page:
+ zero: "No %{plural} found"
+ one: "Displaying 1 %{name}"
+ other: "Displaying all %{count} %{plural}"
+ single_page_html:
+ zero: "No %{plural} found"
+ one: "Displaying <b>1</b> %{name}"
+ other: "Displaying <b>all&nbsp;%{count}</b> %{plural}"
+
+ multi_page: "Displaying %{plural} %{from} - %{to} of %{total} in total"
+ multi_page_html: "Displaying %{plural} <b class='range'>%{from}&nbsp;-&nbsp;%{to}</b> of <b class='total'>%{total}</b> in total"
@@ -15,8 +15,11 @@ class Railtie < Rails::Railtie
ActiveSupport.on_load :action_view do
require 'will_paginate/view_helpers/action_view'
- include WillPaginate::ViewHelpers::ActionView
+ include WillPaginate::ActionView
end
+
+ locale_path = File.expand_path('../locale', __FILE__)
+ config.i18n.railties_load_path.concat Dir["#{locale_path}/*.{rb,yml}"]
end
end
end
@@ -1,4 +1,5 @@
-require 'will_paginate/deprecation'
+# encoding: utf-8
+require 'will_paginate/core_ext'
module WillPaginate
# = Will Paginate view helpers
@@ -7,36 +8,156 @@ module WillPaginate
# for the given collection. The helper itself is lightweight and serves only
# as a wrapper around LinkRenderer instantiation; the renderer then does
# all the hard work of generating the HTML.
- #
- # Read more in WillPaginate::ViewHelpers::Base
module ViewHelpers
- # ==== Global options for helpers
- #
- # Options for pagination helpers are optional and get their default values
- # from the WillPaginate::ViewHelpers.pagination_options hash. You can write
- # to this hash to override default options on the global level:
- #
- # WillPaginate::ViewHelpers.pagination_options[:previous_label] = 'Previous page'
- #
- # By putting this into your environment.rb you can easily translate link
- # texts to previous and next pages, as well as override some other defaults
- # to your liking.
- def self.pagination_options() @pagination_options; end
- # Overrides the default +pagination_options+
- def self.pagination_options=(value) @pagination_options = value; end
-
+ class << self
+ # Write to this hash to override default options on the global level:
+ #
+ # WillPaginate::ViewHelpers.pagination_options[:page_links] = false
+ #
+ attr_accessor :pagination_options
+ end
+
+ # default view options
self.pagination_options = {
:class => 'pagination',
- :previous_label => '&#8592; Previous',
- :next_label => 'Next &#8594;',
+ :previous_label => nil,
+ :next_label => nil,
:inner_window => 4, # links around the current page
:outer_window => 1, # links around beginning and end
- :separator => ' ', # single space is friendly to spiders and non-graphic browsers
+ :link_separator => ' ', # single space is friendly to spiders and non-graphic browsers
:param_name => :page,
:params => nil,
- :renderer => 'WillPaginate::ViewHelpers::LinkRenderer',
+ :renderer => nil,
:page_links => true,
:container => true
}
+
+ # Returns HTML representing page links for a WillPaginate::Collection-like object.
+ # In case there is no more than one page in total, nil is returned.
+ #
+ # ==== Options
+ # * <tt>:class</tt> -- CSS class name for the generated DIV (default: "pagination")
+ # * <tt>:previous_label</tt> -- default: "« Previous"
+ # * <tt>:next_label</tt> -- default: "Next »"
+ # * <tt>:inner_window</tt> -- how many links are shown around the current page (default: 4)
+ # * <tt>:outer_window</tt> -- how many links are around the first and the last page (default: 1)
+ # * <tt>:link_separator</tt> -- string separator for page HTML elements (default: single space)
+ # * <tt>:param_name</tt> -- parameter name for page number in URLs (default: <tt>:page</tt>)
+ # * <tt>:params</tt> -- additional parameters when generating pagination links
+ # (eg. <tt>:controller => "foo", :action => nil</tt>)
+ # * <tt>:renderer</tt> -- class name, class or instance of a link renderer (default:
+ # <tt>WillPaginate::LinkRenderer</tt>)
+ # * <tt>:page_links</tt> -- when false, only previous/next links are rendered (default: true)
+ # * <tt>:container</tt> -- toggles rendering of the DIV container for pagination links, set to
+ # false only when you are rendering your own pagination markup (default: true)
+ #
+ # All options beside listed ones are passed as HTML attributes to the container
+ # element for pagination links (the DIV). For example:
+ #
+ # <%= will_paginate @posts, :style => 'color:blue' %>
+ #
+ # will result in:
+ #
+ # <div class="pagination" style="color:blue"> ... </div>
+ #
+ def will_paginate(collection, options = {})
+ # early exit if there is nothing to render
+ return nil unless collection.total_pages > 1
+
+ options = WillPaginate::ViewHelpers.pagination_options.merge(options)
+
+ scope = 'views.will_paginate'
+ options[:previous_label] ||= will_paginate_translate(:previous_label, :scope => scope) { '&#8592; Previous' }
+ options[:next_label] ||= will_paginate_translate(:next_label, :scope => scope) { 'Next &#8594;' }
+
+ # get the renderer instance
+ renderer = case options[:renderer]
+ when nil
+ raise ArgumentError, ":renderer not specified"
+ when String
+ klass = if options[:renderer].respond_to? :constantize then options[:renderer].constantize
+ else Object.const_get(options[:renderer]) # poor man's constantize
+ end
+ klass.new
+ when Class then options[:renderer].new
+ else options[:renderer]
+ end
+ # render HTML for pagination
+ renderer.prepare collection, options, self
+ renderer.to_html
+ end
+
+ # Renders a helpful message with numbers of displayed vs. total entries.
+ # You can use this as a blueprint for your own, similar helpers.
+ #
+ # <%= page_entries_info @posts %>
+ # #-> Displaying posts 6 - 10 of 26 in total
+ #
+ # By default, the message will use the humanized class name of objects
+ # in collection: for instance, "project types" for ProjectType models.
+ # Override this to your liking with the <tt>:entry_name</tt> parameter:
+ #
+ # <%= page_entries_info @posts, :entry_name => 'item' %>
+ # #-> Displaying items 6 - 10 of 26 in total
+ #
+ # Entry name is entered in singular and pluralized with
+ # <tt>String#pluralize</tt> method from ActiveSupport. If it isn't
+ # loaded, specify plural with <tt>:plural_name</tt> parameter:
+ #
+ # <%= page_entries_info @posts, :entry_name => 'item', :plural_name => 'items' %>
+ #
+ # By default, this method produces HTML output. You can trigger plain
+ # text output by passing <tt>:html => false</tt> in options.
+ def page_entries_info(collection, options = {})
+ entry_name = options[:entry_name] || (collection.empty?? 'entry' :
+ collection.first.class.name.underscore.gsub('_', ' '))
+
+ plural_name = if options[:plural_name]
+ options[:plural_name]
+ elsif entry_name == 'entry'
+ plural_name = 'entries'
+ elsif entry_name.respond_to? :pluralize
+ plural_name = entry_name.pluralize
+ else
+ raise ArgumentError, "must provide :plural_name for #{entry_name.inspect}"
+ end
+
+ unless options[:html] == false
+ b = '<b>'
+ eb = '</b>'
+ sp = '&nbsp;'
+ key = '_html'
+ else
+ b = eb = key = ''
+ sp = ' '
+ end
+
+ scope = 'views.will_paginate.page_entries_info'
+
+ if collection.total_pages < 2
+ will_paginate_translate "single_page#{key}", :scope => scope, :count => collection.size,
+ :name => entry_name, :plural => plural_name do |_, opts|
+ case opts[:count]
+ when 0; "No #{opts[:plural]} found"
+ when 1; "Displaying #{b}1#{eb} #{opts[:name]}"
+ else "Displaying #{b}all #{opts[:count]}#{eb} #{opts[:plural]}"
+ end
+ end
+ else
+ will_paginate_translate "multi_page#{key}", :scope => scope, :total => collection.total_entries, :plural => plural_name,
+ :from => collection.offset + 1, :to => collection.offset + collection.length do |_, opts|
+ %{Displaying %s #{b}%d#{sp}-#{sp}%d#{eb} of #{b}%d#{eb} in total} %
+ [ opts[:plural], opts[:from], opts[:to], opts[:total] ]
+ end
+ end
+ end
+
+ def will_paginate_translate(key, options = {})
+ if defined? ::I18n
+ ::I18n.translate(key, options.merge(:default => Proc.new))
+ else
+ yield key, options
+ end
+ end
end
end
Oops, something went wrong.

0 comments on commit f1fba71

Please sign in to comment.