incubator-heraldry-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From quellho...@apache.org
Subject svn commit: r449142 [23/31] - in /incubator/heraldry: idp/ idp/pip/ idp/pip/branches/ idp/pip/tags/ idp/pip/trunk/ idp/pip/trunk/app/ idp/pip/trunk/app/controllers/ idp/pip/trunk/app/helpers/ idp/pip/trunk/app/models/ idp/pip/trunk/app/views/ idp/pip/t...
Date Sat, 23 Sep 2006 01:37:43 GMT
Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/lib/engines/testing_extensions.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/lib/engines/testing_extensions.rb?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/lib/engines/testing_extensions.rb (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/lib/engines/testing_extensions.rb Fri Sep 22 18:37:26 2006
@@ -0,0 +1,327 @@
+# The Engines testing extensions enable developers to load fixtures into specific
+# tables irrespective of the name of the fixtures file. This work is heavily based on
+# patches made by Duane Johnson (canadaduane), viewable at
+# http://dev.rubyonrails.org/ticket/1911
+#
+# Engine developers should supply fixture files in the <engine>/test/fixtures directory
+# as normal. Within their tests, they should load the fixtures using the 'fixture' command
+# (rather than the normal 'fixtures' command). For example:
+#
+#   class UserTest < Test::Unit::TestCase
+#     fixture :users, :table_name => LoginEngine.config(:user_table), :class_name => "User"
+#    
+#     ...
+#
+# This will ensure that the fixtures/users.yml file will get loaded into the correct
+# table, and will use the correct model object class.
+
+
+
+# A FixtureGroup is a set of fixtures identified by a name.  Normally, this is the name of the
+# corresponding fixture filename.  For example, when you declare the use of fixtures in a
+# TestUnit class, like so:
+#   fixtures :users
+# you are creating a FixtureGroup whose name is 'users', and whose defaults are set such that the
+# +class_name+, +file_name+ and +table_name+ are guessed from the FixtureGroup's name.
+class FixtureGroup
+  attr_accessor :table_name, :class_name, :connection
+  attr_reader :group_name, :file_name
+
+  def initialize(file_name, optional_names = {})
+    self.file_name = file_name
+    self.group_name = optional_names[:group_name] || file_name
+    if optional_names[:table_name]
+      self.table_name = optional_names[:table_name]
+      self.class_name = optional_names[:class_name] || Inflector.classify(@table_name.to_s.gsub('.','_'))
+    elsif optional_names[:class_name]
+      self.class_name = optional_names[:class_name]
+      if Object.const_defined?(@class_name)
+        model_class = Object.const_get(@class_name)
+        self.table_name = ActiveRecord::Base.table_name_prefix + model_class.table_name + ActiveRecord::Base.table_name_suffix
+      end
+    end
+
+    # In case either :table_name or :class_name was not set:
+    self.table_name ||= ActiveRecord::Base.table_name_prefix + @group_name.to_s + ActiveRecord::Base.table_name_suffix
+    self.class_name ||= Inflector.classify(@table_name.to_s.gsub('.','_'))
+  end
+
+  def file_name=(name)
+    @file_name = name.to_s
+  end
+  
+  def group_name=(name)
+    @group_name = name.to_sym
+  end
+
+  def class_file_name
+    Inflector.underscore(@class_name)
+  end
+  
+  # Instantiate an array of FixtureGroup objects from an array of strings (table_names)
+  def self.array_from_names(names)
+    names.collect { |n| FixtureGroup.new(n) }
+  end
+  
+  def hash
+    @group_name.hash
+  end
+  
+  def eql?(other)
+    @group_name.eql? other.group_name
+  end
+end
+
+class Fixtures < YAML::Omap
+
+  def self.instantiate_fixtures(object, fixture_group_name, fixtures, load_instances=true)
+    old_logger_level = ActiveRecord::Base.logger.level
+    ActiveRecord::Base.logger.level = Logger::ERROR
+
+    # table_name.to_s.gsub('.','_') replaced by 'fixture_group_name'
+    object.instance_variable_set "@#{fixture_group_name}", fixtures
+    if load_instances
+      ActiveRecord::Base.silence do
+        fixtures.each do |name, fixture|
+          begin
+            if model = fixture.find
+              object.instance_variable_set "@#{name}", model
+            end
+          rescue FixtureClassNotFound
+            # Let's hope the developer has included it himself
+          end
+        end
+      end
+    end
+
+    ActiveRecord::Base.logger.level = old_logger_level
+  end
+
+  # this doesn't really need to be overridden...
+  def self.instantiate_all_loaded_fixtures(object, load_instances=true)
+    all_loaded_fixtures.each do |fixture_group_name, fixtures|
+      Fixtures.instantiate_fixtures(object, fixture_group_name, fixtures, load_instances)
+    end
+  end
+
+  def self.create_fixtures(fixtures_directory, *fixture_groups)
+    connection = block_given? ? yield : ActiveRecord::Base.connection
+    fixture_groups.flatten!
+    
+    # Backwards compatibility: Allow an array of table names to be passed in, but just use them
+    # to create an array of FixtureGroup objects
+    if not fixture_groups.empty? and fixture_groups.first.is_a?(String)
+      fixture_groups = FixtureGroup.array_from_names(fixture_groups)
+    end
+
+    ActiveRecord::Base.silence do
+      fixtures_map = {}
+      fixtures = fixture_groups.map do |group|
+        fixtures_map[group.group_name] = Fixtures.new(connection, fixtures_directory, group)
+      end 
+      # Make sure all refs to all_loaded_fixtures use group_name as hash index, not table_name
+      all_loaded_fixtures.merge! fixtures_map 
+
+      connection.transaction do
+        fixtures.reverse.each { |fixture| fixture.delete_existing_fixtures }
+        fixtures.each { |fixture| fixture.insert_fixtures }
+        
+        # Cap primary key sequences to max(pk).
+        if connection.respond_to?(:reset_pk_sequence!)
+          fixture_groups.each do |fg|
+            connection.reset_pk_sequence!(fg.table_name)
+          end
+        end
+      end
+
+      return fixtures.size > 1 ? fixtures : fixtures.first
+    end
+  end
+
+ 
+  attr_accessor :connection, :fixtures_directory, :file_filter
+  attr_accessor :fixture_group
+ 
+  def initialize(connection, fixtures_directory, fixture_group, file_filter = DEFAULT_FILTER_RE)
+    @connection, @fixtures_directory = connection, fixtures_directory
+    @fixture_group = fixture_group
+    @file_filter = file_filter
+    read_fixture_files
+  end
+ 
+  def delete_existing_fixtures
+    @connection.delete "DELETE FROM #{@fixture_group.table_name}", 'Fixture Delete'
+  end
+ 
+  def insert_fixtures
+    values.each do |fixture|
+      @connection.execute "INSERT INTO #{@fixture_group.table_name} (#{fixture.key_list}) VALUES (#{fixture.value_list})", 'Fixture Insert'
+    end
+  end
+ 
+  private
+    def read_fixture_files
+      if File.file?(yaml_file_path)
+        read_yaml_fixture_files
+      elsif File.file?(csv_file_path)
+        read_csv_fixture_files
+      elsif File.file?(deprecated_yaml_file_path)
+        raise Fixture::FormatError, ".yml extension required: rename #{deprecated_yaml_file_path} to #{yaml_file_path}"
+      elsif File.directory?(single_file_fixtures_path)
+        read_standard_fixture_files
+      else
+        raise Fixture::FixtureError, "Couldn't find a yaml, csv or standard file to load at #{@fixtures_directory} (#{@fixture_group.file_name})."
+      end
+    end
+
+    def read_yaml_fixture_files
+      # YAML fixtures
+      begin
+        if yaml = YAML::load(erb_render(IO.read(yaml_file_path)))
+          yaml = yaml.value if yaml.respond_to?(:type_id) and yaml.respond_to?(:value)
+          yaml.each do |name, data|
+            self[name] = Fixture.new(data, fixture_group.class_name)
+          end
+        end
+      rescue Exception=>boom
+        raise Fixture::FormatError, "a YAML error occured parsing #{yaml_file_path}. Please note that YAML must be consistently indented using spaces. Tabs are not allowed. Please have a look at http://www.yaml.org/faq.html\nThe exact error was:\n  #{boom.class}: #{boom}"
+      end      
+    end
+
+    def read_csv_fixture_files
+      # CSV fixtures
+      reader = CSV::Reader.create(erb_render(IO.read(csv_file_path)))
+      header = reader.shift
+      i = 0
+      reader.each do |row|
+        data = {}
+        row.each_with_index { |cell, j| data[header[j].to_s.strip] = cell.to_s.strip }
+        self["#{@fixture_group.class_file_name}_#{i+=1}"]= Fixture.new(data, @fixture_group.class_name)
+      end
+    end
+
+    def read_standard_fixture_files
+      # Standard fixtures
+      path = File.join(@fixtures_directory, @fixture_group.file_name)
+      Dir.entries(path).each do |file|
+        path = File.join(@fixtures_directory, @fixture_group.file_name, file)
+        if File.file?(path) and file !~ @file_filter
+          self[file] = Fixture.new(path, @fixture_group.class_name)
+        end
+      end
+    end
+ 
+    def yaml_file_path
+      fixture_path_with_extension ".yml"
+    end
+ 
+    def deprecated_yaml_file_path
+      fixture_path_with_extension ".yaml"
+    end
+ 
+    def csv_file_path
+      fixture_path_with_extension ".csv"
+    end
+    
+    def single_file_fixtures_path
+      fixture_path_with_extension ""
+    end
+ 
+    def fixture_path_with_extension(ext)
+      File.join(@fixtures_directory, @fixture_group.file_name + ext)
+    end 
+
+    def erb_render(fixture_content)
+      ERB.new(fixture_content).result
+    end
+
+end
+
+module Test #:nodoc:
+  module Unit #:nodoc:
+    class TestCase #:nodoc:
+      cattr_accessor :fixtures_directory
+      class_inheritable_accessor :fixture_groups
+      class_inheritable_accessor :fixture_table_names
+      class_inheritable_accessor :use_transactional_fixtures
+      class_inheritable_accessor :use_instantiated_fixtures   # true, false, or :no_instances
+      class_inheritable_accessor :pre_loaded_fixtures
+
+      self.fixture_groups = []
+      self.use_transactional_fixtures = false
+      self.use_instantiated_fixtures = true
+      self.pre_loaded_fixtures = false
+
+      @@already_loaded_fixtures = {}
+
+      # Backwards compatibility
+      def self.fixture_path=(path); self.fixtures_directory = path; end
+      def self.fixture_path; self.fixtures_directory; end
+      def fixture_group_names; fixture_groups.collect { |g| g.group_name }; end
+      def fixture_table_names; fixture_group_names; end
+
+      def self.fixture(file_name, options = {})
+        self.fixture_groups |= [FixtureGroup.new(file_name, options)]
+        require_fixture_classes
+        setup_fixture_accessors
+      end
+
+      def self.fixtures(*file_names)
+        self.fixture_groups |= FixtureGroup.array_from_names(file_names.flatten)
+        require_fixture_classes
+        setup_fixture_accessors
+      end
+
+      def self.require_fixture_classes(fixture_groups_override = nil)
+        (fixture_groups_override || fixture_groups).each do |group| 
+          begin
+            require group.class_file_name
+          rescue LoadError
+            # Let's hope the developer has included it himself
+          end
+        end
+      end
+
+      def self.setup_fixture_accessors(fixture_groups_override=nil)
+        (fixture_groups_override || fixture_groups).each do |group|
+          define_method(group.group_name) do |fixture, *optionals|
+            force_reload = optionals.shift
+            @fixture_cache[group.group_name] ||= Hash.new
+            @fixture_cache[group.group_name][fixture] = nil if force_reload
+            @fixture_cache[group.group_name][fixture] ||= @loaded_fixtures[group.group_name][fixture.to_s].find
+          end
+        end
+      end
+
+      private
+        def load_fixtures
+          @loaded_fixtures = {}
+          fixtures = Fixtures.create_fixtures(fixtures_directory, fixture_groups)
+          unless fixtures.nil?
+            if fixtures.instance_of?(Fixtures)
+              @loaded_fixtures[fixtures.fixture_group.group_name] = fixtures
+            else
+              fixtures.each { |f| @loaded_fixtures[f.fixture_group.group_name] = f }
+            end
+          end
+        end
+
+        def instantiate_fixtures
+          if pre_loaded_fixtures
+            raise RuntimeError, 'Load fixtures before instantiating them.' if Fixtures.all_loaded_fixtures.empty?
+            unless @@required_fixture_classes
+              groups = Fixtures.all_loaded_fixtures.values.collect { |f| f.group_name }
+              self.class.require_fixture_classes groups
+              @@required_fixture_classes = true
+            end
+            Fixtures.instantiate_all_loaded_fixtures(self, load_instances?)
+          else
+            raise RuntimeError, 'Load fixtures before instantiating them.' if @loaded_fixtures.nil?
+            @loaded_fixtures.each do |fixture_group_name, fixtures|
+              Fixtures.instantiate_fixtures(self, fixture_group_name, fixtures, load_instances?)
+            end
+          end
+        end
+    end
+  end
+end

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/tasks/deprecated_engines.rake
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/tasks/deprecated_engines.rake?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/tasks/deprecated_engines.rake (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/tasks/deprecated_engines.rake Fri Sep 22 18:37:26 2006
@@ -0,0 +1,7 @@
+# Old-style engines rake tasks.
+# NOTE: THESE ARE DEPRICATED! PLEASE USE THE NEW STYLE!
+
+task :engine_info => "engines:info"
+task :engine_migrate => "db:migrate:engines"
+task :enginedoc => "doc:engines"
+task :load_plugin_fixtures => "db:fixtures:engines:load"
\ No newline at end of file

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/tasks/engines.rake
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/tasks/engines.rake?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/tasks/engines.rake (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/tasks/engines.rake Fri Sep 22 18:37:26 2006
@@ -0,0 +1,176 @@
+module Engines
+  module RakeTasks
+    def self.all_engines
+      # An engine is informally defined as any subdirectory in vendor/plugins
+      # which ends in '_engine', '_bundle', or contains an 'init_engine.rb' file.
+      engine_base_dirs = ['vendor/plugins']
+      # The engine root may be different; if possible try to include
+      # those directories too
+      if Engines.const_defined?(:CONFIG)
+        engine_base_dirs << Engines::CONFIG[:root]
+      end
+      engine_base_dirs.map! {|d| [d + '/*_engine/*', 
+                                  d + '/*_bundle/*',
+                                  d + '/*/init_engine.rb']}.flatten!
+      engine_dirs = FileList.new(*engine_base_dirs)
+      engine_dirs.map do |engine| 
+        File.basename(File.dirname(engine))
+      end.uniq       
+    end
+  end
+end
+
+
+namespace :engines do
+  desc "Display version information about active engines"
+  task :info => :environment do
+    if ENV["ENGINE"]
+      e = Engines.get(ENV["ENGINE"])
+      header = "Details for engine '#{e.name}':"
+      puts header
+      puts "-" * header.length
+      puts "Version: #{e.version}"
+      puts "Details: #{e.info}"
+    else
+      puts "Engines plugin: #{Engines.version}"
+      Engines.each do |e|
+        puts "#{e.name}: #{e.version}"
+      end
+    end
+  end
+end
+
+namespace :db do  
+  namespace :fixtures do
+    namespace :engines do
+      
+      desc "Load plugin/engine fixtures into the current environment's database."
+      task :load => :environment do
+        require 'active_record/fixtures'
+        ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
+        plugin = ENV['ENGINE'] || '*'
+        Dir.glob(File.join(RAILS_ROOT, 'vendor', 'plugins', plugin, 'test', 'fixtures', '*.yml')).each do |fixture_file|
+          Fixtures.create_fixtures(File.dirname(fixture_file), File.basename(fixture_file, '.*'))
+        end
+      end
+      
+    end
+  end
+
+
+  namespace :migrate do
+    
+    desc "Migrate all engines. Target specific version with VERSION=x, specific engine with ENGINE=x"
+    task :engines => :environment do
+      engines_to_migrate = ENV["ENGINE"] ? [Engines.get(ENV["ENGINE"])].compact : Engines.active
+      if engines_to_migrate.empty?
+        puts "Couldn't find an engine called '#{ENV["ENGINE"]}'"
+      else
+        if ENV["VERSION"] && !ENV["ENGINE"]
+          # ignore the VERSION, since it makes no sense in this context; we wouldn't
+          # want to revert ALL engines to the same version because of a misttype
+          puts "Ignoring the given version (#{ENV["VERSION"]})."
+          puts "To control individual engine versions, use the ENGINE=<engine> argument"
+        else
+          engines_to_migrate.each do |engine| 
+            Engines::EngineMigrator.current_engine = engine
+            migration_directory = File.join(engine.root, 'db', 'migrate')
+            if File.exist?(migration_directory)
+              puts "Migrating engine '#{engine.name}'"
+              Engines::EngineMigrator.migrate(migration_directory, ENV["VERSION"] ? ENV["VERSION"].to_i : nil)
+            else
+              puts "The db/migrate directory for engine '#{engine.name}' appears to be missing."
+              puts "Should be: #{migration_directory}"
+            end
+          end
+          if ActiveRecord::Base.schema_format == :ruby && !engines_to_migrate.empty?
+            Rake::Task[:db_schema_dump].invoke
+          end
+        end
+      end
+    end
+
+    namespace :engines do
+      Engines::RakeTasks.all_engines.each do |engine_name|
+        desc "Migrate the '#{engine_name}' engine. Target specific version with VERSION=x"
+        task engine_name => :environment do
+          ENV['ENGINE'] = engine_name; Rake::Task['db:migrate:engines'].invoke
+        end
+      end
+    end
+    
+  end
+end
+
+
+# this is just a rip-off from the plugin stuff in railties/lib/tasks/documentation.rake, 
+# because the default plugindoc stuff doesn't support subdirectories like <engine>/app or
+# <engine>/component.
+namespace :doc do
+
+  desc "Generate documation for all installed engines"
+  task :engines => Engines::RakeTasks.all_engines.map {|engine| "doc:engines:#{engine}"}
+
+  namespace :engines do
+    # Define doc tasks for each engine
+    Engines::RakeTasks.all_engines.each do |engine_name|
+      desc "Generation documentation for the '#{engine_name}' engine"
+      task engine_name => :environment do
+        engine_base   = "vendor/plugins/#{engine_name}"
+        options       = []
+        files         = Rake::FileList.new
+        options << "-o doc/plugins/#{engine_name}"
+        options << "--title '#{engine_name.titlecase} Documentation'"
+        options << '--line-numbers --inline-source'
+        options << '--all' # include protected methods
+        options << '-T html'
+
+        files.include("#{engine_base}/lib/**/*.rb")
+        files.include("#{engine_base}/app/**/*.rb") # include the app directory
+        files.include("#{engine_base}/components/**/*.rb") # include the components directory
+        if File.exists?("#{engine_base}/README")
+          files.include("#{engine_base}/README")    
+          options << "--main '#{engine_base}/README'"
+        end
+        files.include("#{engine_base}/CHANGELOG") if File.exists?("#{engine_base}/CHANGELOG")
+
+        options << files.to_s
+
+        sh %(rdoc #{options * ' '})
+      end
+    end
+  end
+end
+
+namespace :test do
+  desc "Run the engine tests in vendor/plugins/**/test (or specify with ENGINE=name)"
+  # NOTE: we're using the Rails 1.0 non-namespaced task here, just to maintain
+  # compatibility with Rails 1.0
+  # TODO: make this work with Engines.config(:root)
+  
+  namespace :engines do
+    Engines::RakeTasks.all_engines.each do |engine_name|
+      desc "Run the engine tests for '#{engine_name}'"
+      Rake::TestTask.new(engine_name => :prepare_test_database) do |t|
+        t.libs << 'test'
+        t.pattern = "vendor/plugins/#{engine_name}/test/**/*_test.rb"
+        t.verbose = true
+      end
+    end    
+  end
+  
+  Rake::TestTask.new(:engines => [:warn_about_multiple_engines_testing, :prepare_test_database]) do |t|
+    t.libs << "test"
+    engines = ENV['ENGINE'] || '**'
+    t.pattern = "vendor/plugins/#{engines}/test/**/*_test.rb"
+    t.verbose = true
+  end
+  
+  task :warn_about_multiple_engines_testing do
+    puts %{-~============== A Moste Polite Warninge ==================~-
+You may experience issues testing multiple engines at once. 
+Please test engines individual for the moment.
+-~===============( ... as you were ... )===================~-
+}
+  end
+end
\ No newline at end of file

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/test/action_view_extensions_test.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/test/action_view_extensions_test.rb?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/test/action_view_extensions_test.rb (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/test/action_view_extensions_test.rb Fri Sep 22 18:37:26 2006
@@ -0,0 +1,9 @@
+ENV["RAILS_ENV"] = "test"
+require File.expand_path(File.dirname(__FILE__) + '/../../../../config/environment')
+require 'test_help'
+
+class ActionViewExtensionsTest < Test::Unit::TestCase
+  def test_stylesheet_path
+    assert true
+  end
+end
\ No newline at end of file

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/test/ruby_extensions_test.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/test/ruby_extensions_test.rb?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/test/ruby_extensions_test.rb (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/engines/test/ruby_extensions_test.rb Fri Sep 22 18:37:26 2006
@@ -0,0 +1,115 @@
+ENV["RAILS_ENV"] = "test"
+require File.expand_path(File.dirname(__FILE__) + '/../../../../config/environment')
+require 'test_help'
+
+class RubyExtensionsTest < Test::Unit::TestCase
+
+  def setup
+    # create the module to be used for config testing
+    eval "module TestModule end"
+  end  
+
+  def teardown
+    # remove the TestModule constant from our scope
+    self.class.class_eval { remove_const :TestModule }
+  end
+
+
+  #
+  # Module.config
+  #
+
+  def test_config_no_arguments
+    assert_raise(RuntimeError) { TestModule.config }
+  end
+  
+  def test_config_array_arguments
+    TestModule.config :monkey, 123
+    assert_equal(123, TestModule.config(:monkey))
+  end
+  
+  def test_config_hash_arguments
+    TestModule.config :monkey => 123, :donkey => 456
+    assert_equal(123, TestModule.config(:monkey))
+    assert_equal(456, TestModule.config(:donkey))
+  end
+
+  def test_config_can_store_hash
+    TestModule.config :hash, :key1 => 'val1', :key2 => 'val2'
+    assert_equal({:key1 => 'val1', :key2 => 'val2'}, TestModule.config(:hash))
+  end
+    
+  def test_config_cant_overwrite_existing_config_values
+    TestModule.config :monkey, 123
+    assert_equal(123, TestModule.config(:monkey))
+    TestModule.config :monkey, 456
+    assert_equal(123, TestModule.config(:monkey))
+    
+    TestModule.config :monkey => 456
+    assert_equal(123, TestModule.config(:monkey))    
+    
+    # in this case, the resulting Hash only has {:baboon => "goodbye!"} - that's Ruby, users beware.
+    TestModule.config :baboon => "hello", :baboon => "goodbye!"
+    assert_equal("goodbye!", TestModule.config(:baboon))    
+  end
+  
+  def test_config_force_new_value
+    TestModule.config :monkey, 123
+    TestModule.config :man, 321
+    assert_equal(123, TestModule.config(:monkey))
+    assert_equal(321, TestModule.config(:man))
+    TestModule.config :monkey, 456, :force
+    assert_equal(456, TestModule.config(:monkey))  
+    TestModule.config :monkey => 456, :man => 654, :force => true
+    assert_equal(456, TestModule.config(:monkey))
+    assert_equal(654, TestModule.config(:man))      
+    TestModule.config :monkey => 789, :man => 987, :force => false
+    assert_equal(456, TestModule.config(:monkey))
+    assert_equal(654, TestModule.config(:man))
+    
+    TestModule.config :hash, :key1 => 'val1', :key2 => 'val2'
+    assert_equal({:key1 => 'val1', :key2 => 'val2'}, TestModule.config(:hash))
+    TestModule.config :hash => {:key1 => 'val3', :key2 => 'val4'}, :force => true
+    assert_equal({:key1 => 'val3', :key2 => 'val4'}, TestModule.config(:hash))           
+  end
+  
+  # this test is somewhat redundant, but it might be an idea to havbe it explictly anyway
+  def test_config_get_values
+    TestModule.config :monkey, 123
+    assert_equal(123, TestModule.config(:monkey))
+  end
+  
+  def test_config_get_multiple_values
+    TestModule.config :monkey, 123
+    TestModule.config :donkey, 456
+    assert_equal([123, 456], TestModule.config([:monkey, :donkey]))
+  end
+  
+  
+  #
+  # Module.default_constant
+  #
+  
+  def test_default_constant_set
+    TestModule.default_constant :Monkey, 123
+    assert_equal(123, TestModule::Monkey)
+    TestModule.default_constant "Hello", 456
+    assert_equal(456, TestModule::Hello)
+  end
+
+  def test_default_constant_cannot_set_again
+    TestModule.default_constant :Monkey, 789
+    assert_equal(789, TestModule::Monkey)
+    TestModule.default_constant :Monkey, 456
+    assert_equal(789, TestModule::Monkey)
+  end
+
+  def test_default_constant_bad_arguments
+    # constant names must be Captialized
+    assert_raise(NameError) { TestModule.default_constant :lowercase_name, 123 }
+    
+    # constant names should be given as Strings or Symbols
+    assert_raise(RuntimeError) { TestModule.default_constant 123, 456 }
+    assert_raise(RuntimeError) { TestModule.default_constant Object.new, 456 }
+  end
+end

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/README
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/README?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/README (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/README Fri Sep 22 18:37:26 2006
@@ -0,0 +1,111 @@
+= Exception Notifier Plugin for Rails
+
+The Exception Notifier plugin provides a mailer object and a default set of
+templates for sending email notifications when errors occur in a Rails
+application. The plugin is configurable, allowing programmers to specify:
+
+* the sender address of the email
+* the recipient addresses
+* the text used to prefix the subject line
+
+The email includes information about the current request, session, and
+environment, and also gives a backtrace of the exception.
+
+== Usage
+
+First, include the ExceptionNotifiable mixin in whichever controller you want
+to generate error emails (typically ApplicationController):
+
+  class ApplicationController < ActionController::Base
+    include ExceptionNotifiable
+    ...
+  end
+
+Then, specify the email recipients in your environment:
+
+  ExceptionNotifier.exception_recipients = %w(joe@schmoe.com bill@schmoe.com)
+
+And that's it! The defaults take care of the rest.
+
+== Configuration
+
+You can tweak other values to your liking, as well. In your environment file,
+just set any or all of the following values:
+
+  # defaults to exception.notifier@default.com
+  ExceptionNotifier.sender_address =
+    %("Application Error" <app.error@myapp.com>)
+
+  # defaults to "[ERROR] "
+  ExceptionNotifier.email_prefix = "[APP] "
+
+Email notifications will only occur when the IP address is determined not to
+be local. You can specify certain addresses to always be local so that you'll
+get a detailed error instead of the generic error page. You do this in your
+controller (or even per-controller):
+
+  consider_local "64.72.18.143", "14.17.21.25"
+
+You can specify subnet masks as well, so that all matching addresses are
+considered local:
+
+  consider_local "64.72.18.143/24"
+
+The address "127.0.0.1" is always considered local. If you want to completely
+reset the list of all addresses (for instance, if you wanted "127.0.0.1" to
+NOT be considered local), you can simply do, somewhere in your controller:
+
+  local_addresses.clear
+
+== Customization
+
+By default, the notification email includes four parts: request, session,
+environment, and backtrace (in that order). You can customize how each of those
+sections are rendered by placing a partial named for that part in your
+app/views/exception_notifier directory (e.g., _session.rhtml). Each partial has
+access to the following variables:
+
+* @controller: the controller that caused the error
+* @request: the current request object
+* @exception: the exception that was raised
+* @host: the name of the host that made the request
+* @backtrace: a sanitized version of the exception's backtrace
+* @rails_root: a sanitized version of RAILS_ROOT
+* @data: a hash of optional data values that were passed to the notifier
+* @sections: the array of sections to include in the email
+
+You can reorder the sections, or exclude sections completely, by altering the
+ExceptionNotifier.sections variable. You can even add new sections that
+describe application-specific data--just add the section's name to the list
+(whereever you'd like), and define the corresponding partial. Then, if your
+new section requires information that isn't available by default, make sure
+it is made available to the email using the exception_data macro:
+
+  class ApplicationController < ActionController::Base
+    ...
+    protected
+      exception_data :additional_data
+
+      def additional_data
+        { :document => @document,
+          :person => @person }
+      end
+    ...
+  end
+
+In the above case, @document and @person would be made available to the email
+renderer, allowing your new section(s) to access and display them. See the
+existing sections defined by the plugin for examples of how to write your own.
+
+== Advanced Customization
+
+By default, the email notifier will only notify on critical errors. For
+ActiveRecord::RecordNotFound and ActionController::UnknownAction, it will
+simply render the contents of your public/404.html file. Other exceptions
+will render public/500.html and will send the email notification. If you want
+to use different rules for the notification, you will need to implement your
+own rescue_action_in_public method. You can look at the default implementation
+in ExceptionNotifiable for an example of how to go about that.
+
+
+Copyright (c) 2005 Jamis Buck, released under the MIT license
\ No newline at end of file

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/init.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/init.rb?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/init.rb (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/init.rb Fri Sep 22 18:37:26 2006
@@ -0,0 +1 @@
+require "action_mailer"

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/lib/exception_notifiable.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/lib/exception_notifiable.rb?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/lib/exception_notifiable.rb (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/lib/exception_notifiable.rb Fri Sep 22 18:37:26 2006
@@ -0,0 +1,101 @@
+require 'ipaddr'
+
+# Copyright (c) 2005 Jamis Buck
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+module ExceptionNotifiable
+  def self.included(target)
+    target.extend(ClassMethods)
+  end
+
+  module ClassMethods
+    def consider_local(*args)
+      local_addresses.concat(args.flatten.map { |a| IPAddr.new(a) })
+    end
+
+    def local_addresses
+      addresses = read_inheritable_attribute(:local_addresses)
+      unless addresses
+        addresses = [IPAddr.new("127.0.0.1")]
+        write_inheritable_attribute(:local_addresses, addresses)
+      end
+      addresses
+    end
+
+    def exception_data(deliverer=self)
+      if deliverer == self
+        read_inheritable_attribute(:exception_data)
+      else
+        write_inheritable_attribute(:exception_data, deliverer)
+      end
+    end
+  end
+
+  def local_request?
+    remote = IPAddr.new(request.remote_ip)
+    !self.class.local_addresses.detect { |addr| addr.include?(remote) }.nil?
+  end
+
+  def render_404
+    respond_to do |type|
+      type.html { render :file => "#{RAILS_ROOT}/public/404.html", :status => "404 Not Found" }
+      type.all  { render :nothing => true, :status => "404 Not Found" }
+    end
+  end
+
+  def render_openid_500
+    respond_to do |type|
+      type.html { render :template => "errors/server_index", :status => "500 Error" }
+      type.all  { render :nothing => true, :status => "500 Error" }
+    end
+  end
+
+  def render_500
+    respond_to do |type|
+      type.html { render :file => "#{RAILS_ROOT}/public/500.html", :status => "500 Error" }
+      type.all  { render :nothing => true, :status => "500 Error" }
+    end
+  end
+
+  def rescue_action_in_public(exception)
+    case exception
+      when OpenID::Server::EncodingError
+      when ActiveRecord::RecordNotFound, ActionController::UnknownController, ActionController::UnknownAction
+        render_404
+      else          
+        case exception
+        when OpenID::Server::EncodingError, OpenID::Server::ProtocolError
+          render_openid_500
+        else
+          render_500
+        end
+        deliverer = self.class.exception_data
+        data = case deliverer
+          when nil then {}
+          when Symbol then send(deliverer)
+          when Proc then deliverer.call(self)
+        end
+
+        ExceptionNotifier.deliver_exception_notification(exception, self,
+          request, data)
+    end
+  end
+
+end

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/lib/exception_notifier.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/lib/exception_notifier.rb?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/lib/exception_notifier.rb (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/lib/exception_notifier.rb Fri Sep 22 18:37:26 2006
@@ -0,0 +1,67 @@
+require 'pathname'
+
+# Copyright (c) 2005 Jamis Buck
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+class ExceptionNotifier < ActionMailer::Base
+  @@sender_address = %("Exception Notifier" <exception.notifier@default.com>)
+  cattr_accessor :sender_address
+
+  @@exception_recipients = []
+  cattr_accessor :exception_recipients
+
+  @@email_prefix = "[ERROR] "
+  cattr_accessor :email_prefix
+
+  @@sections = %w(request session environment backtrace)
+  cattr_accessor :sections
+
+  def self.reloadable?; false; end
+
+  def exception_notification(exception, controller, request, data={})
+    subject    "#{email_prefix}#{controller.controller_name}##{controller.action_name} (#{exception.class}) #{exception.message.inspect}"
+
+    recipients exception_recipients
+    from       sender_address
+
+    body       data.merge({ :controller => controller, :request => request,
+                  :exception => exception, :host => request.env["HTTP_HOST"],
+                  :backtrace => sanitize_backtrace(exception.backtrace),
+                  :rails_root => rails_root, :data => data,
+                  :sections => sections })
+  end
+
+  def template_root
+    "#{File.dirname(__FILE__)}/../views"
+  end
+
+  private
+
+    def sanitize_backtrace(trace)
+      re = Regexp.new(/^#{Regexp.escape(rails_root)}/)
+      trace.map { |line| Pathname.new(line.gsub(re, "[RAILS_ROOT]")).cleanpath.to_s }
+    end
+
+    def rails_root
+      return @rails_root if @rails_root
+      @rails_root = Pathname.new(RAILS_ROOT).cleanpath.to_s
+    end
+
+end

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/lib/exception_notifier_helper.rb Fri Sep 22 18:37:26 2006
@@ -0,0 +1,63 @@
+require 'pp'
+
+# Copyright (c) 2005 Jamis Buck
+#
+# Permission is hereby granted, free of charge, to any person obtaining
+# a copy of this software and associated documentation files (the
+# "Software"), to deal in the Software without restriction, including
+# without limitation the rights to use, copy, modify, merge, publish,
+# distribute, sublicense, and/or sell copies of the Software, and to
+# permit persons to whom the Software is furnished to do so, subject to
+# the following conditions:
+#
+# The above copyright notice and this permission notice shall be
+# included in all copies or substantial portions of the Software.
+#
+# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
+# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
+# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
+# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
+# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+module ExceptionNotifierHelper
+  VIEW_PATH = "views/exception_notifier"
+  APP_PATH = "#{RAILS_ROOT}/app/#{VIEW_PATH}"
+
+  def render_section(section)
+    RAILS_DEFAULT_LOGGER.info("rendering section #{section.inspect}")
+    summary = render_overridable(section).strip
+    unless summary.blank?
+      title = render_overridable(:title, :locals => { :title => section }).strip
+      "#{title}\n\n#{summary.gsub(/^/, "  ")}\n\n"
+    end
+  end
+
+  def render_overridable(partial, options={})
+    if File.exist?(path = "#{APP_PATH}/_#{partial}.rhtml")
+      render(options.merge(:file => path, :use_full_path => false))
+    elsif File.exist?(path = "#{File.dirname(__FILE__)}/../#{VIEW_PATH}/_#{partial}.rhtml")
+      render(options.merge(:file => path, :use_full_path => false))
+    else
+      ""
+    end
+  end
+
+  def inspect_model_object(model, locals={})
+    render_overridable(:inspect_model,
+      :locals => { :inspect_model => model,
+                   :show_instance_variables => true,
+                   :show_attributes => true }.merge(locals))
+  end
+
+  def inspect_value(value)
+    len = 512
+    result = object_to_yaml(value).gsub(/\n/, "\n  ").strip
+    result = result[0,len] + "... (#{result.length-len} bytes more)" if result.length > len+20
+    result
+  end
+
+  def object_to_yaml(object)
+    object.to_yaml.sub(/^---\s*/m, "")
+  end
+end

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_backtrace.rhtml
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_backtrace.rhtml?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_backtrace.rhtml (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_backtrace.rhtml Fri Sep 22 18:37:26 2006
@@ -0,0 +1 @@
+<%= @backtrace.join "\n" %>

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_environment.rhtml
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_environment.rhtml?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_environment.rhtml (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_environment.rhtml Fri Sep 22 18:37:26 2006
@@ -0,0 +1,7 @@
+<% max = @request.env.keys.max { |a,b| a.length <=> b.length } -%>
+<% @request.env.keys.sort.each do |key| -%>
+* <%= "%*-s: %s" % [max.length, key, @request.env[key].to_s.strip] %>
+<% end -%>
+
+* Process: <%= $$ %>
+* Server : <%= `hostname -s`.chomp %>

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_inspect_model.rhtml
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_inspect_model.rhtml?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_inspect_model.rhtml (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_inspect_model.rhtml Fri Sep 22 18:37:26 2006
@@ -0,0 +1,16 @@
+<% if show_attributes -%>
+[attributes]
+<% attrs = inspect_model.attributes -%>
+<% max = attrs.keys.max { |a,b| a.length <=> b.length } -%>
+<% attrs.keys.sort.each do |attr| -%>
+* <%= "%*-s: %s" % [max.length, attr, object_to_yaml(attrs[attr]).gsub(/\n/, "\n  ")] %>
+<% end -%>
+<% end -%>
+
+<% if show_instance_variables -%>
+[instance variables]
+<% inspect_model.instance_variables.sort.each do |variable| -%>
+<%- next if variable == "@attributes" -%>
+* <%= variable %>: <%= inspect_value(inspect_model.instance_variable_get(variable)) %>
+<% end -%>
+<% end -%>

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_request.rhtml
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_request.rhtml?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_request.rhtml (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_request.rhtml Fri Sep 22 18:37:26 2006
@@ -0,0 +1,3 @@
+* URL: <%= @request.protocol %><%= @host %><%= @request.request_uri %>
+* Parameters: <%= @request.parameters.inspect %>
+* Rails root: <%= @rails_root %>

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_session.rhtml
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_session.rhtml?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_session.rhtml (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_session.rhtml Fri Sep 22 18:37:26 2006
@@ -0,0 +1,4 @@
+<% for variable in @request.session.instance_variables -%>
+<% next if variable =~ /^@db/ -%>
+* <%= variable %>: <%= PP.pp(@request.session.instance_variable_get(variable),"").gsub(/\n/, "\n  ").strip %>
+<% end -%>

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_title.rhtml
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_title.rhtml?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_title.rhtml (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/_title.rhtml Fri Sep 22 18:37:26 2006
@@ -0,0 +1,3 @@
+-------------------------------
+<%= title.to_s.humanize %>:
+-------------------------------

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/exception_notification.rhtml
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/exception_notification.rhtml?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/exception_notification.rhtml (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/exception_notification/views/exception_notifier/exception_notification.rhtml Fri Sep 22 18:37:26 2006
@@ -0,0 +1,6 @@
+A <%= @exception.class %> occurred in <%= @controller.controller_name %>#<%= @controller.action_name %>:
+
+  <%= @exception.message %>
+  <%= @backtrace.first %>
+
+<%= @sections.map { |section| render_section(section) }.join %>

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/LICENSE
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/LICENSE?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/LICENSE (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/LICENSE Fri Sep 22 18:37:26 2006
@@ -0,0 +1,9 @@
+Copyright (c) 2005 Joshua Harvey [Jerusalem, Israel]
+
+This is the MIT license, the license Ruby on Rails itself is licensed under.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/README
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/README?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/README (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/README Fri Sep 22 18:37:26 2006
@@ -0,0 +1,49 @@
+=Welcome to Globalize
+
+*Globalize* is a Ruby on Rails plugin designed to support globalized applications. It supports translation into multiple languages (for both db content and controller and view code) and localization of time, data, and numbers. It's under the MIT License, same as Ruby on Rails.
+
+==How to use it
+
+===In your models
+
+  class Product < ActiveRecord::Base
+    translates :name, :description, :specs
+  end
+
+Then:
+
+  Locale.set("en-US")
+  prod = Product.find(1) 
+
+<tt>prod.name -> "Meatballs"</tt>
+
+  Locale.set("es-ES")
+  prod = Product.find(1) 
+
+<tt>prod.name -> "Albondigas"</tt>
+
+=== In your views (or anywhere else)
+
+  Locale.set("he-IL")
+  <%= "Thanks for ordering!".t %> -> "תודה על ההזמנה!" 
+  <%= "You've got %d items in your cart" / 5 %> -> "יש 5 מוצרים בסל שלך"
+
+  Locale.set("es-ES")
+  <%= Time.now.loc("%d %B %Y") %> -> "17 Octubre 2005"
+  <%= 12345.45.loc %> -> "12.345,45"
+
+There's more, but let's save that for later.
+
+==How to install
+
+From your rails app root directory:
+
+1. <tt>script/plugin install http://svn.globalize-rails.org/svn/globalize/globalize/trunk</tt>
+1. <tt>rake globalize:setup</tt> (might take a while, about a minute or so)
+
+...and you're globalized, dude!
+
+Optionally, try:
+
+* <tt>rake test_plugins</tt>
+* <tt>rake plugindoc</tt>

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/data/country_data.csv
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/data/country_data.csv?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/data/country_data.csv (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/data/country_data.csv Fri Sep 22 18:37:26 2006
@@ -0,0 +1,240 @@
+"id","code","english_name","date_format","currency_format","currency_code","thousands_sep","decimal_sep","currency_decimal_sep","number_grouping_scheme"
+1,"AD","Andorra",,,"EUR",,,,"western"
+2,"AE","United Arab Emirates",,,"AED",",",".",".","western"
+3,"AF","Afghanistan",,,"AFA",,,,"western"
+4,"AG","Antigua and Barbuda",,,"XCD",,,,"western"
+5,"AI","Anguilla",,,"XCD",,,,"western"
+6,"AL","Albania",,,"ALL",".",",",",","western"
+7,"AM","Armenia",,,"AMD",,,,"western"
+8,"AN","Netherlands Antilles",,,"ANG",,,,"western"
+9,"AO","Angola",,,"AON",,,,"western"
+10,"AQ","Antarctica",,,"NOK",,,,"western"
+11,"AR","Argentina",,,"ARA",".",",",",","western"
+12,"AS","American Samoa",,,"USD",,,,"western"
+13,"AT","Austria",,"€ %n","EUR",,",",",","western"
+14,"AU","Australia",,,"AUD",",",".",".","western"
+15,"AW","Aruba",,,"AWG",,,,"western"
+16,"AZ","Azerbaijan",,,"AZM",,".",".","western"
+17,"BA","Bosnia and Herzegovina",,,"BAM",,",",",","western"
+18,"BB","Barbados",,,"BBD",,,,"western"
+19,"BD","Bangladesh",,,"BDT",",",".",".","western"
+20,"BE","Belgium",,"%n €","EUR",".",",",",","western"
+21,"BF","Burkina Faso",,,"XAF",,,,"western"
+22,"BG","Bulgaria",,,"BGL"," ",",",",","western"
+23,"BH","Bahrain",,,"BHD",",",".",".","western"
+24,"BI","Burundi",,,"BIF",,,,"western"
+25,"BJ","Benin",,,"XAF",,,,"western"
+26,"BM","Bermuda",,,"BMD",,,,"western"
+27,"BN","Brunei Darussalam",,,"BND",,,,"western"
+28,"BO","Bolivia",,,"BOB",".",",",",","western"
+29,"BR","Brazil",,"R$%n","BRR",".",",",",","western"
+30,"BS","Bahamas",,,"BSD",,,,"western"
+31,"BT","Bhutan",,,"BTN",,,,"western"
+32,"BV","Bouvet Island",,,"NOK",,,,"western"
+33,"BW","Botswana",,,"BWP",",",".",".","western"
+34,"BY","Belarus",,,"BYR",,".",".","western"
+35,"BZ","Belize",,,"BZD",,,,"western"
+36,"CA","Canada",,,"CAD",",",".",".","western"
+37,"CC","Cocos  Islands",,,"AUD",,,,"western"
+38,"CD","Congo",,,,,,,"western"
+39,"CF","Central African Republic",,,"XAF",,,,"western"
+40,"CG","Congo",,,"XAF",,,,"western"
+41,"CH","Switzerland",,"SFr. %n","CHF","'",",",".","western"
+42,"CI","Cote D'Ivoire",,,"XAF",,,,"western"
+43,"CK","Cook Islands",,,"NZD",,,,"western"
+44,"CL","Chile",,,"CLF",".",",",",","western"
+45,"CM","Cameroon",,,"XAF",,,,"western"
+46,"CN","China",,"Y%n","CNY",",",".",".","western"
+47,"CO","Colombia",,,"COP",".",",",",","western"
+48,"CR","Costa Rica",,,"CRC",",",".",".","western"
+49,"CS","Serbia and Montenegro",,,"CSD",,,,"western"
+50,"CU","Cuba",,,"CUP",,,,"western"
+51,"CV","Cape Verde",,,"CVE",,,,"western"
+52,"CX","Christmas Island",,,"AUD",,,,"western"
+53,"CY","Cyprus",,,"CYP",,,,"western"
+54,"CZ","Czech Republic",,,"CZK"," ",",",",","western"
+55,"DE","Germany",,"%n €","EUR",".",",",",","western"
+56,"DJ","Djibouti",,,"DJF",,,,"western"
+57,"DK","Denmark",,,"DKK",".",",",",","western"
+58,"DM","Dominica",,,"XCD",,,,"western"
+59,"DO","Dominican Republic",,,"DOP",",",".",".","western"
+60,"DZ","Algeria",,,"DZD",",",".",".","western"
+61,"EC","Ecuador",,,"USD",".",",",",","western"
+62,"EE","Estonia",,,"EEK"," ",",",",","western"
+63,"EG","Egypt",,,"EGP",",",".",".","western"
+64,"EH","Western Sahara",,,"MAD",,,,"western"
+65,"ER","Eritrea",,,"ERN",",",".",".","western"
+66,"ES","Spain",,"%n €","EUR",".",",",",","western"
+67,"ET","Ethiopia",,,"ETB",",",".",".","western"
+68,"FI","Finland",,,"EUR"," ",",",",","western"
+69,"FJ","Fiji",,,"FJD",,,,"western"
+70,"FK","Falkland Islands",,,"FKP",,,,"western"
+71,"FM","Micronesia",,,"USD",,,,"western"
+72,"FO","Faeroe Islands",,,"DKK",".",",",",","western"
+73,"FR","France",,"%n €","EUR",,",",",","western"
+74,"GA","Gabon",,,"XAF",,,,"western"
+75,"GB","United Kingdom",,"£%n","GBP",",",".",".","western"
+76,"GD","Grenada",,,"XCD",,,,"western"
+77,"GE","Georgia",,,"GEL",".",",",",","western"
+78,"GF","French Guiana",,,"EUR",,,,"western"
+79,"GH","Ghana",,,"GHC",,,,"western"
+80,"GI","Gibraltar",,,"GIP",,,,"western"
+81,"GL","Greenland",,,"DKK",".",",",",","western"
+82,"GM","Gambia",,,"GMD",,,,"western"
+83,"GN","Guinea",,,"GNS",,,,"western"
+84,"GP","Guadaloupe",,,"EUR",,,,"western"
+85,"GQ","Equatorial Guinea",,,"XAF",,,,"western"
+86,"GR","Greece",,,"EUR",".",",",",","western"
+87,"GS","South Georgia and the South Sandwich Islands",,,"GBP",,,,"western"
+88,"GT","Guatemala",,,"GTQ",",",".",".","western"
+89,"GU","Guam",,,"USD",,,,"western"
+90,"GW","Guinea-Bissau",,,"GWP",,,,"western"
+91,"GY","Guyana",,,"GYD",,,,"western"
+92,"HK","Hong Kong",,"HK$%n","HKD",",",".",".","western"
+93,"HM","Heard and McDonald Islands",,,"AUD",,,,"western"
+94,"HN","Honduras",,,"HNL",",",".",".","western"
+95,"HR","Hrvatska",,,"HRK",,",",",","western"
+96,"HT","Haiti",,,"HTG",,,,"western"
+97,"HU","Hungary",,,"HUF",".",",",",","western"
+98,"ID","Indonesia",,,"IDR",".",",",",","western"
+99,"IE","Ireland",,,"EUR",",",".",".","western"
+100,"IL","Israel",,"%n ₪","ILS",",",".",".","western"
+101,"IN","India",,"Rs.%n","INR",",",".",".","indian"
+102,"IO","British Indian Ocean Territory",,,"GBP",,,,"western"
+103,"IQ","Iraq",,,"IQD",",",".",".","western"
+104,"IR","Iran",,,"IRR","Ù¬","Ù«","Ù«","western"
+105,"IS","Iceland",,,"ISK",".",",",",","western"
+106,"IT","Italy",,"€ %n","EUR",".",",",",","western"
+107,"JM","Jamaica",,,"JMD",,,,"western"
+108,"JO","Jordan",,,"JOD",",",".",".","western"
+109,"JP","Japan",,"Â¥%n","JPY",",",".",".","western"
+110,"KE","Kenya",,,"KES",,,,"western"
+111,"KG","Kyrgyz Republic",,,"KGS",,,,"western"
+112,"KH","Cambodia",,,"KHR",,,,"western"
+113,"KI","Kiribati",,,"AUD",,,,"western"
+114,"KM","Comoros",,,"KMF",,,,"western"
+115,"KN","St. Kitts and Nevis",,,"XCD",,,,"western"
+116,"KP","Korea",,,"KPW",,,,"western"
+117,"KR","Korea",,,"KRW",",",".",".","western"
+118,"KW","Kuwait",,,"KWD",",",".",".","western"
+119,"KY","Cayman Islands",,,"KYD",,,,"western"
+120,"KZ","Kazakhstan",,,"KZT",,,,"western"
+121,"LA","Lao People's Democratic Republic",,,"LAK",",",".",".","western"
+122,"LB","Lebanon",,,"LBP",",",".",".","western"
+123,"LC","St. Lucia",,,"XCD",,,,"western"
+124,"LI","Liechtenstein",,,"CHF",,,,"western"
+125,"LK","Sri Lanka",,,"LKR",,,,"western"
+126,"LR","Liberia",,,"LRD",,,,"western"
+127,"LS","Lesotho",,,"LSL",,,,"western"
+128,"LT","Lithuania",,,"LTL",".",",",",","western"
+129,"LU","Luxembourg",,,"EUR",".",",",",","western"
+130,"LV","Latvia",,,"LVL"," ",",",",","western"
+131,"LY","Libyan Arab Jamahiriya",,,"LYD",",",".",".","western"
+132,"MA","Morocco",,,"MAD",",",".",".","western"
+133,"MC","Monaco",,,"EUR",,,,"western"
+134,"MD","Moldova",,,"MDL",,,,"western"
+135,"MG","Madagascar",,,"MGF",,,,"western"
+136,"MH","Marshall Islands",,,"USD",,,,"western"
+137,"MK","Macedonia",,,"MKD",,",",",","western"
+138,"ML","Mali",,,"XAF",,,,"western"
+139,"MM","Myanmar",,,,,,,"western"
+140,"MN","Mongolia",,,"MNT",,".",".","western"
+141,"MO","Macao",,,"MOP",,,,"western"
+142,"MP","Northern Mariana Islands",,,"USD",,,,"western"
+143,"MQ","Martinique",,,"EUR",,,,"western"
+144,"MR","Mauritania",,,"MRO",,,,"western"
+145,"MS","Montserrat",,,"XCD",,,,"western"
+146,"MT","Malta",,,"MTL",",",".",".","western"
+147,"MU","Mauritius",,,"MUR",,,,"western"
+148,"MV","Maldives",,,"MVR",,,,"western"
+149,"MW","Malawi",,,"MWK",,,,"western"
+150,"MX","Mexico",,,"MXN",",",".",".","western"
+151,"MY","Malaysia",,,"MYR",",",".",".","western"
+152,"MZ","Mozambique",,,"MZM",,,,"western"
+153,"NA","Namibia",,,"NAD",,,,"western"
+154,"NC","New Caledonia",,,"XPF",,,,"western"
+155,"NE","Niger",,,"XOF",,,,"western"
+156,"NF","Norfolk Island",,,"AUD",,,,"western"
+157,"NG","Nigeria",,,"NGN",,,,"western"
+158,"NI","Nicaragua",,,"NIC",",",".",".","western"
+159,"NL","Netherlands",,"€ %n","EUR",,",",",","western"
+160,"NO","Norway",,"kr %n","NOK"," ",",",",","western"
+161,"NP","Nepal",,,"NPR",",",".",".","western"
+162,"NR","Nauru",,,"AUD",,,,"western"
+163,"NU","Niue",,,"NZD",,,,"western"
+164,"NZ","New Zealand",,,"NZD",",",".",".","western"
+165,"OM","Oman",,,"OMR",",",".",".","western"
+166,"PA","Panama",,,"PAB",",",".",".","western"
+167,"PE","Peru",,,"PEI",",",".",".","western"
+168,"PF","French Polynesia",,,"XPF",,,,"western"
+169,"PG","Papua New Guinea",,,"PGK",,,,"western"
+170,"PH","Philippines",,,"PHP",",",".",".","western"
+171,"PK","Pakistan",,,"PKR",",",".",".","western"
+172,"PL","Poland",,,"PLN",".",",",",","western"
+173,"PM","St. Pierre and Miquelon",,,"EUR",,,,"western"
+174,"PN","Pitcairn Island",,,"NZD",,,,"western"
+175,"PR","Puerto Rico",,,"USD",",",".",".","western"
+176,"PS","Palestinian Territory",,,,,,,"western"
+177,"PT","Portugal",,"%n €","EUR",".","$","$","western"
+178,"PW","Palau",,,"USD",,,,"western"
+179,"PY","Paraguay",,,"PYG",".",",",",","western"
+180,"QA","Qatar",,,"QAR",",",".",".","western"
+181,"RE","Reunion",,,"EUR",,,,"western"
+182,"RO","Romania",,,"ROL",".",",",",","western"
+183,"RU","Russian Federation",,,"RUB",,".",".","western"
+184,"RW","Rwanda",,,"RWF",,,,"western"
+185,"SA","Saudi Arabia",,,"SAR",,".",".","western"
+186,"SB","Solomon Islands",,,"SBD",,,,"western"
+187,"SC","Seychelles",,,"SCR",,,,"western"
+188,"SD","Sudan",,,"SDP",",",".",".","western"
+189,"SE","Sweden",,"%n kr","SEK",,",",",","western"
+190,"SG","Singapore",,,"SGD",",",".",".","western"
+191,"SH","St. Helena",,,"SHP",,,,"western"
+192,"SI","Slovenia",,,"SIT",,",",",","western"
+193,"SJ","Svalbard & Jan Mayen Islands",,,"NOK",,,,"western"
+194,"SK","Slovakia",,,"SKK"," ",",",",","western"
+195,"SL","Sierra Leone",,,"SLL",,,,"western"
+196,"SM","San Marino",,,"EUR",,,,"western"
+197,"SN","Senegal",,,"XOF",,,,"western"
+198,"SO","Somalia",,,"SOS",,,,"western"
+199,"SR","Suriname",,,"SRG",,,,"western"
+200,"ST","Sao Tome and Principe",,,"STD",,,,"western"
+201,"SV","El Salvador",,,"SVC",",",".",".","western"
+202,"SY","Syrian Arab Republic",,,"SYP",",",".",".","western"
+203,"SZ","Swaziland",,,"SZL",,,,"western"
+204,"TC","Turks and Caicos Islands",,,"USD",,,,"western"
+205,"TD","Chad",,,"XAF",,,,"western"
+206,"TF","French Southern Territories",,,"EUR",,,,"western"
+207,"TG","Togo",,,"XAF",,,,"western"
+208,"TH","Thailand",,,"THB",",",".",".","western"
+209,"TJ","Tajikistan",,,"TJR",,".",".","western"
+210,"TK","Tokelau",,,"NZD",,,,"western"
+211,"TL","Timor-Leste",,,,,,,"western"
+212,"TM","Turkmenistan",,,"TMM",,,,"western"
+213,"TN","Tunisia",,,"TND",",",".",".","western"
+214,"TO","Tonga",,,"TOP",,,,"western"
+215,"TR","Turkey",,,"TRL",".",",",",","western"
+216,"TT","Trinidad and Tobago",,,"TTD",,,,"western"
+217,"TV","Tuvalu",,,"AUD",,,,"western"
+218,"TW","Taiwan",,"NT$%n","TWD",",",".",".","western"
+219,"TZ","Tanzania",,,"TZS",,,,"western"
+220,"UA","Ukraine",,,"UAH",,".",".","western"
+221,"UG","Uganda",,,"UGS",",",".",".","western"
+222,"UM","United States Minor Outlying Islands",,,"USD",,,,"western"
+223,"US","United States of America",,,"USD",",",".",".","western"
+224,"UY","Uruguay",,,"UYU",".",",",",","western"
+225,"UZ","Uzbekistan",,,"UZS",",",".",".","western"
+226,"VA","Holy See",,,"EUR",,,,"western"
+227,"VC","St. Vincent and the Grenadines",,,"XCD",,,,"western"
+228,"VE","Venezuela",,,"VEB",".",",",",","western"
+229,"VG","British Virgin Islands",,,"USD",,,,"western"
+230,"VI","US Virgin Islands",,,"USD",,,,"western"
+231,"VN","Viet Nam",,,"VND",".",",",",","western"
+232,"VU","Vanuatu",,,"VUV",,,,"western"
+233,"WF","Wallis and Futuna Islands",,,"XPF",,,,"western"
+234,"WS","Samoa",,,"WST",,,,"western"
+235,"YE","Yemen",,,,",",".",".","western"
+236,"YT","Mayotte",,,"EUR",,,,"western"
+237,"ZA","South Africa",,,"ZAR",",",".",".","western"
+238,"ZM","Zambia",,,"ZMK",,,,"western"
+239,"ZW","Zimbabwe",,,"ZWD",",",".",".","western"

Added: incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/data/language_data.csv
URL: http://svn.apache.org/viewvc/incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/data/language_data.csv?view=auto&rev=449142
==============================================================================
--- incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/data/language_data.csv (added)
+++ incubator/heraldry/idp/pip/trunk/vendor/plugins/globalize/data/language_data.csv Fri Sep 22 18:37:26 2006
@@ -0,0 +1,188 @@
+"id","iso_639_1","iso_639_2","iso_639_3","rfc_3066","english_name","english_name_locale","english_name_modifier","native_name","native_name_locale","native_name_modifier","macro_language","direction","pluralization","scope"
+
+15,"aa","aar","aar",,"Afar",,,,,,0,"ltr",,"L"
+33,"ab","abk","abk",,"Abkhazian",,,"аҧсуа бызшәа",,,0,"ltr",,"L"
+114,"af","afr","afr",,"Afrikaans",,,"Afrikaans",,,0,"ltr",,"L"
+191,"ak","aka","aka",,"Akan",,,,,,1,"ltr",,"L"
+247,"am","amh","amh",,"Amharic",,,"አማርኛ",,,0,"ltr",,"L"
+340,"ar","ara","ara",,"Arabic",,,"العربية",,,1,"rtl",,"L"
+346,"an","arg","arg",,"Aragonese",,,,,,0,"ltr",,"L"
+376,"as","asm","asm",,"Assamese",,,,,,0,"ltr",,"L"
+438,"av","ava","ava",,"Avaric",,,,,,0,"ltr",,"L"
+441,"ae","ave","ave",,"Avestan",,,,,,0,"ltr",,"A"
+483,"ay","aym","aym",,"Aymara",,,,,,1,"ltr",,"L"
+496,"az","aze","aze",,"Azerbaijani",,,"azərbaycan",,,1,"ltr",,"L"
+512,"ba","bak","bak",,"Bashkir",,,,,,0,"ltr",,"L"
+514,"bm","bam","bam",,"Bambara",,,"Bamanankan",,,0,"ltr",,"L"
+614,"be","bel","bel",,"Belarusian",,,"Беларуская",,,0,"ltr",,"L"
+616,"bn","ben","ben",,"Bengali",,,,,,0,"ltr",,"L"
+721,"bi","bis","bis",,"Bislama",,,,,,0,"ltr",,"L"
+860,"bo","bod","bod",,"Tibetan",,,,,,0,"ltr",,"L"
+875,"bs","bos","bos",,"Bosnian",,,,,,0,"ltr",,"L"
+936,"br","bre","bre",,"Breton",,,,,,0,"ltr",,"L"
+1020,"bg","bul","bul",,"Bulgarian",,,"Български",,,0,"ltr",,"L"
+1177,"ca","cat","cat",,"Catalan",,,"Català",,,0,"ltr",,"L"
+1233,"cs","ces","ces",,"Czech",,,"čeština",,,0,"ltr","c%10==1 && c%100!=11 ? 1 : c%10>=2 && c%10<=4 && (c%100<10 || c%100>=20) ? 2 : 3","L"
+1242,"ch","cha","cha",,"Chamorro",,,,,,0,"ltr",,"L"
+1246,"ce","che","che",,"Chechen",,,,,,0,"ltr",,"L"
+1261,"cu","chu","chu",,"Slavic",,"Church",,,,0,"ltr",,"A"
+1262,"cv","chv","chv",,"Chuvash",,,,,,0,"ltr",,"L"
+1372,"kw","cor","cor",,"Cornish",,,,,,0,"ltr",,"L"
+1373,"co","cos","cos",,"Corsican",,,,,,0,"ltr",,"L"
+1397,"cr","cre","cre",,"Cree",,,,,,1,"ltr",,"L"
+1481,"cy","cym","cym",,"Welsh",,,"Cymraeg",,,0,"ltr",,"L"
+1499,"da","dan","dan",,"Danish",,,"Dansk",,,0,"ltr","c == 1 ? 1 : 2","L"
+1556,"de","deu","deu",,"German",,,"Deutsch",,,0,"ltr","c == 1 ? 1 : 2","L"
+1607,"dv","div","div",,"Divehi",,,,,,0,"ltr",,"L"
+1760,"dz","dzo","dzo",,"Dzongkha",,,,,,0,"ltr",,"L"
+1793,"el","ell","ell",,"Greek",,"Modern (1453-)","Ελληνικά",,,0,"ltr","c == 1 ? 1 : 2","L"
+1819,"en","eng","eng",,"English",,,,,,0,"ltr","c == 1 ? 1 : 2","L"
+1831,"eo","epo","epo",,"Esperanto",,,,,,0,"ltr","c == 1 ? 1 : 2","C"
+1851,"et","est","est",,"Estonian",,,"Eesti",,,0,"ltr","c == 1 ? 1 : 2","L"
+1865,"eu","eus","eus",,"Basque",,,"euskera",,,0,"ltr",,"L"
+1869,"ee","ewe","ewe",,"Ewe",,,"Ɛʋɛ",,,0,"ltr",,"L"
+1886,"fo","fao","fao",,"Faroese",,,,,,0,"ltr",,"L"
+1889,"fa","fas","fas",,"Persian",,,"فارسی",,,1,"ltr",,"L"
+1901,"fj","fij","fij",,"Fijian",,,,,,0,"ltr",,"L"
+1903,"fi","fin","fin",,"Finnish",,,"suomi",,,0,"ltr","c == 1 ? 1 : 2","L"
+1930,"fr","fra","fra",,"French",,,"français",,,0,"ltr","c == 1 ? 1 : 2","L"
+1942,"fy","fry","fry",,"Frisian",,,,,,1,"ltr",,"L"
+1954,"ff","ful","ful",,"Fulah",,,"Fulfulde, Pulaar, Pular",,,1,"ltr",,"L"
+2112,"gd","gla","gla",,"Gaelic","Scots",,,,,0,"ltr","c==1 ? 1 : c==2 ? 2 : 3","L"
+2115,"ga","gle","gle",,"Irish",,,"Gaeilge",,,0,"ltr","c==1 ? 1 : c==2 ? 2 : 3","L"
+2116,"gl","glg","glg",,"Gallegan",,,"Galego",,,0,"ltr",,"L"
+2125,"gv","glv","glv",,"Manx",,,,,,0,"ltr",,"E"
+2194,"gn","grn","grn",,"Guarani",,,,,,1,"ltr",,"L"
+2226,"gu","guj","guj",,"Gujarati",,,,,,0,"ltr",,"L"
+2304,"ht","hat","hat",,"Haitian; Haitian Creole",,,,,,0,"ltr",,"L"
+2305,"ha","hau","hau",,"Hausa",,,"Hausa",,,0,"ltr",,"L"
+2315,"sh",,"hbs",,"Serbo-Croatian",,,,,,1,"ltr",,"L"
+2323,"he","heb","heb",,"Hebrew",,,"עברית",,,0,"rtl","c == 1 ? 1 : 2","L"
+2329,"hz","her","her",,"Herero",,,,,,0,"ltr",,"L"
+2343,"hi","hin","hin",,"Hindi",,,"हिंदी",,,0,"ltr",,"L"
+2370,"ho","hmo","hmo",,"Hiri Motu",,,,,,0,"ltr",,"L"
+2418,"hr","hrv","hrv",,"Croatian",,,"Hrvatski",,,0,"ltr","c%10==1 && c%100!=11 ? 1 : c%10>=2 && c%10<=4 && (c%100<10 || c%100>=20) ? 2 : 3","L"
+2443,"hu","hun","hun",,"Hungarian",,,"Magyar",,,0,"ltr","c = 1","L"
+2466,"hy","hye","hye",,"Armenian",,,"Հայերեն",,,0,"ltr",,"L"
+2480,"ig","ibo","ibo",,"Igbo",,,,,,0,"ltr",,"L"
+2494,"io","ido","ido",,"Ido",,,,,,0,"ltr",,"C"
+2519,"ii","iii","iii",,"Yi",,"Sichuan",,,,0,"ltr",,"L"
+2532,"iu","iku","iku",,"Inuktitut",,,,,,1,"ltr",,"L"
+2539,"ie","ile","ile",,"Interlingue",,,,,,0,"ltr",,"C"
+2556,"ia","ina","ina",,"Interlingua","International Auxiliary Language Association",,,,,0,"ltr",,"C"
+2558,"id","ind","ind",,"Indonesian",,,"Bahasa indonesia",,,0,"ltr",,"L"
+2574,"ik","ipk","ipk",,"Inupiaq",,,,,,1,"ltr",,"L"
+2593,"is","isl","isl",,"Icelandic",,,"Íslenska",,,0,"ltr",,"L"
+2600,"it","ita","ita",,"Italian",,,"italiano",,,0,"ltr","c == 1 ? 1 : 2","L"
+2652,"jv","jav","jav",,"Javanese",,,,,,0,"ltr",,"L"
+2723,"ja","jpn","jpn",,"Japanese",,,"日本語",,,0,"ltr","c = 1","L"
+2763,"kl","kal","kal",,"Kalaallisut",,,,,,0,"ltr",,"L"
+2765,"kn","kan","kan",,"Kannada",,,"ಕನ್ನಡ",,,0,"ltr",,"L"
+2769,"ks","kas","kas",,"Kashmiri",,,,,,0,"ltr",,"L"
+2770,"ka","kat","kat",,"Georgian",,,,,,0,"ltr",,"L"
+2771,"kr","kau","kau",,"Kanuri",,,,,,1,"ltr",,"L"
+2776,"kk","kaz","kaz",,"Kazakh",,,"Қазақ",,,0,"ltr",,"L"
+2939,"km","khm","khm",,"Khmer",,,,,,0,"ltr",,"L"
+2963,"ki","kik","kik",,"Kikuyu",,,,,,0,"ltr",,"L"
+2966,"rw","kin","kin",,"Kinyarwanda",,,"Kinyarwanda",,,0,"ltr",,"L"
+2970,"ky","kir","kir",,"Kirghiz",,,"Кыргыз",,,0,"ltr",,"L"
+3117,"kv","kom","kom",,"Komi",,,,,,1,"ltr",,"L"
+3118,"kg","kon","kon",,"Kongo",,,,,,1,"ltr",,"L"
+3122,"ko","kor","kor",,"Korean",,,"한국어",,,0,"ltr","c = 1","L"
+3260,"kj","kua","kua",,"Kuanyama",,,,,,0,"ltr",,"L"
+3276,"ku","kur","kur",,"Kurdish",,,,,,1,"ltr",,"L"
+3428,"lo","lao","lao",,"Lao",,,,,,0,"ltr",,"L"
+3433,"la","lat","lat",,"Latin",,,,,,0,"ltr",,"A"
+3435,"lv","lav","lav",,"Latvian",,,"Latviešu",,,0,"ltr","c%10==1 && c%100!=11 ? 1 : c != 0 ? 2 : 3","L"
+3546,"li","lim","lim",,"Limburgish",,"Limburger",,,,0,"ltr",,"L"
+3547,"ln","lin","lin",,"Lingala",,,,,,0,"ltr",,"L"
+3553,"lt","lit","lit",,"Lithuanian",,,"Lietuviškai",,,0,"ltr","c%10==1 && c%100!=11 ? 1 : c%10>=2 && (c%100<10 || c%100>=20) ? 2 : 3","L"
+3687,"lb","ltz","ltz",,"Letzeburgesch",,,,,,0,"ltr",,"L"
+3689,"lu","lub","lub",,"Luba-Katanga",,,,,,0,"ltr",,"L"
+3694,"lg","lug","lug",,"Ganda",,,,,,0,"ltr",,"L"
+3732,"mh","mah","mah",,"Marshall",,,,,,0,"ltr",,"L"
+3736,"ml","mal","mal",,"Malayalam",,,,,,0,"ltr",,"L"
+3740,"mr","mar","mar",,"Marathi",,,,,,0,"ltr",,"L"
+3981,"mk","mkd","mkd",,"Macedonian",,,"Македонски",,,0,"ltr",,"L"
+4009,"mg","mlg","mlg",,"Malagasy",,,,,,1,"ltr",,"L"
+4022,"mt","mlt","mlt",,"Maltese",,,"Malti",,,0,"ltr",,"L"
+4091,"mo","mol","mol",,"Moldavian",,,,,,0,"ltr",,"L"
+4093,"mn","mon","mon",,"Mongolian",,,,,,1,"ltr",,"L"
+4166,"mi","mri","mri",,"Maori",,,,,,0,"ltr",,"L"
+4184,"ms","msa","msa",,"Malay","generic",,"Bahasa melayu",,,1,"ltr",,"L"
+4338,"my","mya","mya",,"Burmese",,,,,,0,"ltr",,"L"
+4406,"na","nau","nau",,"Nauru",,,,,,0,"ltr",,"L"
+4407,"nv","nav","nav",,"Navajo",,,,,,0,"ltr",,"L"
+4423,"nr","nbl","nbl",,"Ndebele",,"South",,,,0,"ltr",,"L"
+4463,"nd","nde","nde",,"Ndebele",,"North",,,,0,"ltr",,"L"
+4473,"ng","ndo","ndo",,"Ndonga",,,,,,0,"ltr",,"L"
+4499,"ne","nep","nep",,"Nepali",,,,,,0,"ltr",,"L"
+4628,"nl","nld","nld",,"Dutch",,,"Nederlands",,,0,"ltr","c == 1 ? 1 : 2","L"
+4682,"nn","nno","nno",,"Norwegian Nynorsk",,,,,,0,"ltr",,"L"
+4695,"nb","nob","nob",,"Norwegian Bokmål",,,,,,0,"ltr",,"L"
+4709,"no","nor","nor",,"Norwegian",,,"Norsk",,,1,"ltr","c == 1 ? 1 : 2","L"
+4821,"ny","nya","nya",,"Chichewa; Nyanja",,,,,,0,"ltr",,"L"
+4867,"oc","oci","oci",,"Occitan","post 1500",,,,,1,"ltr",,"L"
+4891,"oj","oji","oji",,"Ojibwa",,,,,,1,"ltr",,"L"
+4965,"or","ori","ori",,"Oriya",,,,,,0,"ltr",,"L"
+4967,"om","orm","orm",,"Oromo",,,,,,1,"ltr",,"L"
+4984,"os","oss","oss",,"Ossetian; Ossetic",,,,,,0,"ltr",,"L"
+5031,"pa","pan","pan",,"Panjabi",,,,,,0,"ltr",,"L"
+5176,"pi","pli","pli",,"Pali",,,,,,0,"ltr",,"A"
+5244,"pl","pol","pol",,"Polish",,,"Polski",,,0,"ltr","c==1 ? 1 : c%10>=2 && c%10<=4 && (c%100<10 || c%100>=20) ? 2 : 3","L"
+5250,"pt","por","por",,"Portuguese",,,"português",,,0,"ltr","c == 1 ? 1 : 2","L"
+5343,"ps","pus","pus",,"Pushto",,,"پښتو",,,1,"ltr",,"L"
+5368,"qu","que","que",,"Quechua",,,,,,1,"ltr",,"L"
+5525,"rm","roh","roh",,"Raeto-Romance",,,,,,0,"ltr",,"L"
+5528,"ro","ron","ron",,"Romanian",,,"Română",,,0,"ltr",,"L"
+5552,"rn","run","run",,"Rundi",,,"Kirundi",,,0,"ltr",,"L"
+5556,"ru","rus","rus",,"Russian",,,"Pyccĸий",,,0,"ltr","c%10==1 && c%100!=11 ? 1 : c%10>=2 && c%10<=4 && (c%100<10 || c%100>=20) ? 2 : 3","L"
+5576,"sg","sag","sag",,"Sango",,,,,,0,"ltr",,"L"
+5581,"sa","san","san",,"Sanskrit",,,,,,0,"ltr",,"A"
+5738,"si","sin","sin",,"Sinhalese",,,,,,0,"ltr",,"L"
+5800,"sk","slk","slk",,"Slovak",,,"Slovenčina",,,0,"ltr","c%10==1 && c%100!=11 ? 1 : c%10>=2 && c%10<=4 && (c%100<10 || c%100>=20) ? 2 : 3","L"
+5810,"sl","slv","slv",,"Slovenian",,,"Slovenščina",,,0,"ltr","c%100==1 ? 1 : c%100==2 ? 2 : c%100==3 || c%100==4 ? 3 : 4","L"
+5819,"se","sme","sme",,"Northern Sami",,,,,,0,"ltr",,"L"
+5828,"sm","smo","smo",,"Samoan",,,,,,0,"ltr",,"L"
+5840,"sn","sna","sna",,"Shona",,,,,,0,"ltr",,"L"
+5843,"sd","snd","snd",,"Sindhi",,,,,,0,"ltr",,"L"
+5876,"so","som","som",,"Somali",,,"Somali",,,0,"ltr",,"L"
+5882,"st","sot","sot",,"Sotho",,"Southern",,,,0,"ltr",,"L"
+5889,"es","spa","spa",,"Spanish",,,"Español",,,0,"ltr","c == 1 ? 1 : 2","L"
+5910,"sq","sqi","sqi",,"Albanian",,,"shqip",,,1,"ltr",,"L"
+5921,"sc","srd","srd",,"Sardinian",,,,,,1,"ltr",,"L"
+5933,"sr","srp","srp",,"Serbian",,,"Srpski",,,0,"ltr",,"L"
+5964,"ss","ssw","ssw",,"Swati",,,,,,0,"ltr",,"L"
+6002,"su","sun","sun",,"Sundanese",,,,,,0,"ltr",,"L"
+6021,"sw","swa","swa",,"Swahili","generic",,"Kiswahili",,,1,"ltr",,"L"
+6024,"sv","swe","swe",,"Swedish",,,"svenska",,,0,"ltr","c == 1 ? 1 : 2","L"
+6086,"ty","tah","tah",,"Tahitian",,,,,,0,"ltr",,"L"
+6090,"ta","tam","tam",,"Tamil",,,,,,0,"ltr",,"L"
+6097,"tt","tat","tat",,"Tatar",,,,,,0,"ltr",,"L"
+6182,"te","tel","tel",,"Telugu",,,"తెలుగు",,,0,"ltr",,"L"
+6210,"tg","tgk","tgk",,"Tajik",,,,,,0,"ltr",,"L"
+6211,"tl","tgl","tgl",,"Tagalog",,,,,,0,"ltr",,"L"
+6223,"th","tha","tha",,"Thai",,,"ภาษาไทย",,,0,"ltr",,"L"
+6260,"ti","tir","tir",,"Tigrinya",,,,,,0,"ltr",,"L"
+6383,"to","ton","ton",,"Tonga","Tonga Islands",,,,,0,"ltr",,"L"
+6466,"tn","tsn","tsn",,"Tswana",,,,,,0,"ltr",,"L"
+6467,"ts","tso","tso",,"Tsonga",,,,,,0,"ltr",,"L"
+6513,"tk","tuk","tuk",,"Turkmen",,,,,,0,"ltr",,"L"
+6519,"tr","tur","tur",,"Turkish",,,"Tϋrkçe",,,0,"ltr","c = 1","L"
+6546,"tw","twi","twi",,"Twi",,,,,,0,"ltr",,"L"
+6630,"ug","uig","uig",,"Uighur",,,,,,0,"ltr",,"L"
+6640,"uk","ukr","ukr",,"Ukrainian",,,"Українська",,,0,"ltr","c%10==1 && c%100!=11 ? 1 : c%10>=2 && c%10<=4 && (c%100<10 || c%100>=20) ? 2 : 3","L"
+6679,"ur","urd","urd",,"Urdu",,,"اردو",,,0,"ltr",,"L"
+6719,"uz","uzb","uzb",,"Uzbek",,,"o'zbek",,,1,"ltr",,"L"
+6744,"ve","ven","ven",,"Venda",,,,,,0,"ltr",,"L"
+6751,"vi","vie","vie",,"Vietnamese",,,"Tiếng Việt",,,0,"ltr",,"L"
+6800,"vo","vol","vol",,"Volapük",,,,,,0,"ltr",,"C"
+6911,"wa","wln","wln",,"Walloon",,,,,,0,"ltr",,"L"
+6952,"wo","wol","wol",,"Wolof",,,"Wolof",,,0,"ltr",,"L"
+7078,"xh","xho","xho",,"Xhosa",,,,,,0,"ltr",,"L"
+7324,"yi","yid","yid",,"Yiddish",,,,,,1,"ltr",,"L"
+7481,"za","zha","zha",,"Zhuang",,,,,,1,"ltr",,"L"
+7484,"zh","zho","zho",,"Chinese",,,"中文",,,1,"ltr",,"L"
+7594,"zu","zul","zul",,"Zulu",,,"isiZulu",,,0,"ltr",,"L"
+7595,,,,"zh-Hant","Traditional Chinese",,,,,,0,"ltr",,"L"
+7596,,,,"zh-Hans","Simplified Chinese",,,,,,0,"ltr",,"L"



Mime
View raw message