# = LocalizedCountrySelect
#
# View helper for displaying select list with countries:
#
# localized_country_select(:user, :country)
#
# Works just like the default Rails' +country_select+ plugin, but stores countries as
# country *codes*, not *names*, in the database.
#
# You can easily translate country codes in your application like this:
# <%= I18n.t @user.country, :scope => 'countries' %>
#
# Uses the Rails internationalization framework (I18n) for translating the names of countries.
#
# Use Rake task rake import:country_select 'de' for importing country names
# from Unicode.org's CLDR repository (http://www.unicode.org/cldr/data/charts/summary/root.html)
#
# Code adapted from Rails' default +country_select+ plugin (previously in core)
# See http://github.com/rails/country_select/tree/master/lib/country_select.rb
#
module LocalizedCountrySelect
class << self
# Returns array with codes and localized country names (according to I18n.locale)
# for tags
def localized_countries_array(options={})
exclude = Array(options[:exclude]).map {|code| code.to_s.upcase }
if(options[:description]==:abbreviated)
I18n.translate(:countries).map { |key, value| [key.to_s.upcase] if !exclude.include?(key.to_s.upcase) }
else
I18n.translate(:countries).map { |key, value| [value, key.to_s.upcase] if !exclude.include?(key.to_s.upcase) }
end.compact.sort_by { |country| country.first.parameterize }
end
# Return array with codes and localized country names for array of country codes passed as argument
# == Example
# priority_countries_array([:TW, :CN])
# # => [ ['Taiwan', 'TW'], ['China', 'CN'] ]
def priority_countries_array(country_codes=[],options={})
if(options[:description]==:abbreviated)
country_codes.map { |code| [code.to_s.upcase] }
else
countries = I18n.translate(:countries)
country_codes.map { |code| [countries[code.to_s.upcase.to_sym], code.to_s.upcase] }
end
end
end
end
module ActionView
module Helpers
module FormOptionsHelper
# Return select and option tags for the given object and method, using +localized_country_options_for_select+
# to generate the list of option tags. Uses country code, not name as option +value+.
# Country codes listed as an array of symbols in +priority_countries+ argument will be listed first
# TODO : Implement pseudo-named args with a hash, not the "somebody said PHP?" multiple args sillines
def localized_country_select(object, method, priority_countries = nil, options = {}, html_options = {})
tag = if defined?(ActionView::Helpers::InstanceTag) &&
ActionView::Helpers::InstanceTag.instance_method(:initialize).arity != 0
InstanceTag.new(object, method, self, options.delete(:object))
else
CountrySelect.new(object, method, self, options)
end
tag.to_localized_country_select_tag(priority_countries, options, html_options)
end
alias_method :country_select, :localized_country_select
# Return "named" select and option tags according to given arguments.
# Use +selected_value+ for setting initial value
# It behaves likes older object-binded brother +localized_country_select+ otherwise
# TODO : Implement pseudo-named args with a hash, not the "somebody said PHP?" multiple args sillines
def localized_country_select_tag(name, selected_value = nil, priority_countries = nil, html_options = {})
select_tag name.to_sym, localized_country_options_for_select(selected_value, priority_countries).html_safe, html_options.stringify_keys
end
alias_method :country_select_tag, :localized_country_select_tag
# Returns a string of option tags for countries according to locale. Supply the country code in upper-case ('US', 'DE')
# as +selected+ to have it marked as the selected option tag.
# Country codes listed as an array of symbols in +priority_countries+ argument will be listed first
def localized_country_options_for_select(selected = nil, priority_countries = nil, options={})
country_options = "".html_safe
if priority_countries
country_options += options_for_select(LocalizedCountrySelect::priority_countries_array(priority_countries, options), selected)
country_options += "\n".html_safe
return country_options + options_for_select(LocalizedCountrySelect::localized_countries_array(options) - LocalizedCountrySelect::priority_countries_array(priority_countries, options), selected)
else
return country_options + options_for_select(LocalizedCountrySelect::localized_countries_array(options), selected)
end
end
alias_method :country_options_for_select, :localized_country_options_for_select
end
module ToCountrySelectTag
def to_localized_country_select_tag(priority_countries, options, html_options)
html_options = html_options.stringify_keys
add_default_name_and_id(html_options)
value = value(object)
content_tag("select",
add_options(
localized_country_options_for_select(value, priority_countries, options).html_safe,
options, value
), html_options
)
end
end
if defined?(ActionView::Helpers::InstanceTag) &&
ActionView::Helpers::InstanceTag.instance_method(:initialize).arity != 0
class InstanceTag
include ToCountrySelectTag
end
else
class CountrySelect < Tags::Base
include ToCountrySelectTag
end
end
class FormBuilder
def localized_country_select(method, priority_countries = nil, options = {}, html_options = {})
@template.localized_country_select(@object_name, method, priority_countries, options.merge(:object => @object), html_options)
end
alias_method :country_select, :localized_country_select
end
end
end
if defined?(Rails)
require "localized_country_select/railtie"
end