Permalink
Browse files

Merge remote branch 'koppen/master'

  • Loading branch information...
2 parents e4f0e87 + e1d44d5 commit b9244159968d3225a811ea25fa84918269e1626a @jeremy committed Sep 2, 2010
Showing with 221 additions and 4 deletions.
  1. +9 −1 README.md
  2. +41 −3 lib/country_select.rb
  3. +171 −0 spec/country_select.rb_spec.rb
View
@@ -6,6 +6,14 @@ The list of countries comes from [iso-codes package]( http://svn.debian.org/wsvn
This plugin is modified from Rails [iso-3166-country-select plugin](http://github.com/rails/iso-3166-country-select/tree/master)
and licensed under the [MIT](http://www.opensource.org/licenses/mit-license.php)
+
+## Internationalization
+
+The plugin provides support for translating country names via the Rails I18n framework provided with Rails 2.2 (see the [Rails Internationalization (I18n) API guide](http://guides.rubyonrails.org/i18n.html) for details).
+
+The original english country names are stored in the database and will be used as translation keys when translating the country names into their equivalent names in the current locale.
+
+
## Example
- country_select("user", "country_name")
+ country_select("user", "country_name")
View
@@ -7,22 +7,33 @@ module FormOptionsHelper
def country_select(object, method, priority_countries = nil, options = {}, html_options = {})
InstanceTag.new(object, method, self, options.delete(:object)).to_country_select_tag(priority_countries, options, html_options)
end
+
+ # Returns the full list of known countries
+ def countries
+ COUNTRIES
+ end
+
# Returns a string of option tags for pretty much any country in the world. Supply a country name as +selected+ to
# have it marked as the selected option tag. You can also supply an array of countries as +priority_countries+, so
# that they will be listed above the rest of the (long) list.
+ #
+ # All country names should be given in English and will be passed to the current I18n backend. The text displayed
+ # in each option tag will be the result of the translation, while the value will remain the english value.
#
# NOTE: Only the option tags are returned, you have to wrap this call in a regular HTML select tag.
def country_options_for_select(selected = nil, priority_countries = nil)
country_options = ""
if priority_countries
- country_options += options_for_select(priority_countries, selected)
+ country_options += options_for_select(translate_countries(priority_countries), selected)
country_options += "<option value=\"\" disabled=\"disabled\">-------------</option>\n"
end
- return country_options + options_for_select(COUNTRIES, selected)
+ return country_options + options_for_select(translated_countries, selected)
end
- # All the countries included in the country_options output.
+
+ # All the countries included in the country_options output. These are the original values, are to be used as
+ # translation keys for the Internationalization backend and will be stored in the database.
COUNTRIES = ["Afghanistan","Åland Islands","Albania","Algeria","American Samoa","Andorra","Angola",
"Anguilla","Antarctica","Antigua and Barbuda","Argentina","Armenia","Aruba","Australia","Austria",
"Azerbaijan","Bahamas","Bahrain","Bangladesh","Barbados","Belarus","Belgium","Belize","Benin",
@@ -60,6 +71,32 @@ def country_options_for_select(selected = nil, priority_countries = nil)
"United States","United States Minor Outlying Islands","Uruguay","Uzbekistan","Vanuatu","Venezuela",
"Viet Nam","Virgin Islands, British","Virgin Islands, U.S.","Wallis and Futuna","Western Sahara",
"Yemen","Zambia","Zimbabwe"] unless const_defined?("COUNTRIES")
+
+ private
+
+ # Returns an array with all country names and their translated equivalent in the current locale.
+ def translated_countries
+ translate_countries(countries).sort
+ end
+
+ # Returns an array with the given country names and their translated equivalent in the current locale.
+ def translate_countries(countries = [])
+ return countries unless defined?(I18n)
+
+ countries.collect do |country_name|
+ begin
+ # See if there is a translation for this country name
+ translation = I18n.translate(country_name, :scope => 'countries', :raise => true)
+ rescue I18n::MissingTranslationData
+ # Translation not found for this country, use the original country name, which is probably more correct
+ # than 'translation missing...'
+ translation = country_name
+ end
+
+ [translation, country_name]
+ end
+ end
+
end
class InstanceTag
@@ -81,5 +118,6 @@ def country_select(method, priority_countries = nil, options = {}, html_options
@template.country_select(@object_name, method, priority_countries, options.merge(:object => @object), html_options)
end
end
+
end
end
@@ -0,0 +1,171 @@
+require 'lib/country_select'
+
+describe ActionView::Helpers::FormOptionsHelper do
+
+ # Setup a fake helper for testing
+ class CountrySelectSpecHelper
+ # Use a limited set of countries for testing
+ ActionView::Helpers::FormOptionsHelper::COUNTRIES = ["American Samoa", "Côte d'Ivoire", "Denmark", "Holy See (Vatican City State)"]
+ include ActionView::Helpers::FormOptionsHelper
+ end
+ def helper
+ @helper ||= CountrySelectSpecHelper.new
+ end
+
+ before :each do
+ helper.stub!(:options_for_select).and_return('<option></option>')
+
+ # Easier access to the countries we use for testing
+ @countries = ActionView::Helpers::FormOptionsHelper::COUNTRIES
+ end
+
+ describe "countries" do
+ it "should return the COUNTRIES array" do
+ helper.countries.should == @countries
+ end
+ end
+
+ describe "with I18n not available" do
+ describe "translated_countries" do
+ it "should return the original countries Array" do
+ helper.send(:translated_countries).should == @countries
+ end
+ end
+ end
+
+ describe "with I18n available" do
+ before :each do
+ # Pretend we have I18n available
+ unless defined?(I18n)
+ module I18n
+ class MissingTranslationData < ArgumentError; end
+ end
+ end
+
+ I18n.stub!(:translate).with(any_args()).and_raise(I18n::MissingTranslationData) # No translations for the 'en' language
+
+ # Build an array of translations
+ @translations = @countries.collect do |country|
+ [country, country]
+ end
+ end
+
+ describe "with locale set to 'en'" do
+ describe "translated_countries" do
+ it "should return the default translations" do
+ helper.send(:translated_countries).should == @translations
+ end
+ end
+
+ describe "country_options_for_select" do
+ it "should return a string" do
+ helper.country_options_for_select.should be_instance_of(String)
+ end
+
+ it "should select the selected country" do
+ helper.should_receive(:options_for_select).with(@translations, 'Denmark')
+ result = helper.country_options_for_select('Denmark')
+ end
+
+ describe "with priority countries" do
+ it "should put priority countries at the top" do
+ helper.should_receive(:options_for_select).with([['Denmark', 'Denmark']], 'Ireland')
+ helper.should_receive(:options_for_select).with(@translations, 'Ireland')
+ result = helper.country_options_for_select('Ireland', ['Denmark'])
+ end
+
+ it "should include a separator line" do
+ helper.country_options_for_select('Ireland', ['Denmark']).should match(/<option value="" disabled="disabled">-+<\/option>/)
+ end
+ end
+ end
+ end
+
+ describe "with locale set to 'da'" do
+ before :each do
+ @translations = [
+ ["Amerikansk Samoa", "American Samoa"],
+ ["Danmark", "Denmark"],
+ ["Den Hellige Stol (Vatikan Staten)", 'Holy See (Vatican City State)'],
+ ["Elfenbenskysten", "Côte d'Ivoire"]
+ ]
+
+ # Provide the translations through the backend
+ @translations.each do |danish, english|
+ I18n.stub!(:translate).with(english, :scope => 'countries', :raise => true).and_return(danish)
+ end
+ end
+
+ describe "translated_countries" do
+ it "should return an Array with translated country names" do
+ helper.send(:translated_countries).should be_instance_of(Array)
+ end
+
+ it "should sort the translated values" do
+ @result = ['']
+ helper.should_receive(:translate_countries).and_return(@result)
+ @result.should_receive(:sort)
+ helper.send(:translated_countries)
+ end
+
+ it "should look up each translation in the backend" do
+ @translations.each do |danish, english|
+ I18n.should_receive(:translate).with(english, :scope => 'countries', :raise => true)
+ end
+ helper.send(:translated_countries)
+ end
+
+ it "should use original value if translation isn't known" do
+ # Don't fail when encountering the sovereign state of Petoria.
+ helper.should_receive(:countries).and_return(['Petoria'])
+ I18n.should_receive(:translate).with("Petoria", :scope => 'countries', :raise => true).and_raise(I18n::MissingTranslationData)
+ helper.send(:translated_countries).should == [['Petoria', 'Petoria']]
+ end
+ end
+
+ describe "translate_countries" do
+ it "should return an Array with translated country names" do
+ helper.send(:translate_countries, []).should be_instance_of(Array)
+ end
+
+ it "should look up each translation in the backend" do
+ @translations.each do |danish, english|
+ I18n.should_receive(:translate).with(english, :scope => 'countries', :raise => true)
+ end
+ helper.send(:translate_countries, @translations.collect { |danish, english| english })
+ end
+
+ it "should use original value if translation isn't known" do
+ # Don't fail when encountering the sovereign state of Petoria.
+ I18n.should_receive(:translate).with("Petoria", :scope => 'countries', :raise => true).and_raise(I18n::MissingTranslationData)
+ helper.send(:translate_countries, ['Petoria']).should == [['Petoria', 'Petoria']]
+ end
+ end
+
+ describe "country_options_for_select" do
+
+ it "should select the selected country" do
+ helper.should_receive(:options_for_select).with(@translations, 'Denmark')
+ result = helper.country_options_for_select('Denmark')
+ end
+
+ describe "with priority countries" do
+ it "should put priority countries at the top" do
+ helper.should_receive(:options_for_select).with([['Danmark', 'Denmark']], 'Ireland')
+ helper.should_receive(:options_for_select).with(@translations, 'Ireland')
+ result = helper.country_options_for_select('Ireland', ['Denmark'])
+ end
+
+ it "should include a separator line" do
+ helper.country_options_for_select('Ireland', ['Denmark']).should match(/<option value="" disabled="disabled">-+<\/option>/)
+ end
+
+ it "should translate priority countries" do
+ helper.should_receive(:options_for_select).with([['Danmark', 'Denmark']], nil)
+ result = helper.country_options_for_select(nil, ['Denmark'])
+ end
+ end
+ end
+ end
+ end
+end

0 comments on commit b924415

Please sign in to comment.