=begin
  gettext/rails.rb - GetText for "Ruby on Rails"

  Copyright (C) 2005  Masao Mutoh

  You may redistribute it and/or modify it under the same
  license terms as Ruby.

  $Id: rails.rb,v 1.8 2005/12/28 17:32:58 mutoh Exp $
=end

require 'gettext'
require 'gettext/cgi'
require 'active_record'
require 'active_support'

module GetText
  module Rails
    include GetText

    Rails = ::Rails

    alias :_bindtextdomain :bindtextdomain

    def bindtextdomain(domainname, _cgi = nil, locale = nil, charset = nil, with_model = true)
      set_cgi(_cgi) if _cgi
      @gettext_container_domainname = domainname
      path = File.join(RAILS_ROOT, "locale")
      _bindtextdomain(domainname, path, locale, charset)

      bindtextdomain_to(ActiveRecord::Base, domainname) if with_model
    end

    def bindtextdomain_to(klass, domainname)
      klass.class_eval {
	include GetText::Rails
	extend GetText::Rails
	textdomain(domainname)

	def self.human_attribute_name(attribute_key_name)
	  ret = ""
	  if self == ActiveRecord::Base
	    #Table name
	    ret = _(attribute_key_name.humanize)
	  else
	    ret = s_("#{self}|#{attribute_key_name.humanize}")
	  end
          ret
	end
      }
    end

    def callersrc
      @gettext_container_domainname = nil unless defined? @gettext_container_domainname
      @gettext_container_domainname
    end
  end
end

module ActionController
  class Base
    helper GetText::Rails
    include GetText::Rails
    extend GetText::Rails

    @@gettext_domainname = nil
    @@gettext_content_type = nil

    prepend_before_filter :init_gettext

    def init_gettext_main
      bindtextdomain(@@gettext_domainname, request.cgi)  #You need to pass CGI object first.
      @headers["Content-Type"] = "#{@@gettext_content_type}; charset=#{GetText.output_charset}"
    end

    def init_gettext
      init_gettext_main
      ActiveRecord::Errors.class_eval{
	# You need to call bindtextdomain here because ActiveRecord::Errors doesn't know
	# what locale is used in.
	GetText.bindtextdomain("rails")
      }
    end
    
    def self.init_gettext(domainname, charset = "UTF-8", content_type = "text/html")
      GetText.output_charset = charset
      @@gettext_domainname = domainname
      @@gettext_content_type = content_type
    end
  end
end

module ActiveRecord
  class Errors
    include GetText
    extend GetText
    
    RE_FIELD_NAME = /%\{fn\}/

    # You need to define this here, because this values will be updated by application.
    default_error_messages.update(
				  :inclusion => N_("%{fn} is not included in the list"),
				  :exclusion => N_("%{fn} is reserved"),
				  :invalid => N_("%{fn} is invalid"),
				  :confirmation => N_("%{fn} doesn't match confirmation"),
				  :accepted  => N_("%{fn} must be accepted"),
				  :empty => N_("%{fn} can't be empty"),
				  :blank => N_("%{fn} can't be blank"),
				  :too_long => N_("%{fn} is too long (max is %d characters)"),  
				  :too_short => N_("%{fn} is too short (min is %d characters)"), 
				  :wrong_length => N_("%{fn} is the wrong length (should be %d characters)"),
				  :taken => N_("%{fn} has already been taken"),
				  :not_a_number => N_("%{fn} is not a number")
				  )

    @@default_error_messages_d = {
      :too_long => default_error_messages[:too_long],
      :too_short => default_error_messages[:too_short],
      :wrong_length => default_error_messages[:wrong_length]
    }

    def self.convert_validates_messages_of_validates_length_of
      default_error_messages[:too_long] = _(@@default_error_messages_d[:too_long])
      default_error_messages[:too_short] = _(@@default_error_messages_d[:too_short])
      default_error_messages[:wrong_length] = _(@@default_error_messages_d[:wrong_length])      
    end

    def full_messages
      full_messages = []

      @errors.each_key do |attr|
	@errors[attr].each do |msg|
	  next if msg.nil?
	  if attr == "base"
	    full_messages << _(msg)
	  elsif  RE_FIELD_NAME =~ msg
	    full_messages << _(msg) % {:fn => @base.class.human_attribute_name(attr)}
	  else
	    full_messages << @base.class.human_attribute_name(attr) + " " + msg
	  end
	end
      end
      full_messages
    end
  end

  module Validations
    module ClassMethods
      alias :_validates_length_of :validates_length_of
      def validates_length_of(*attrs)
	ActiveRecord::Errors.convert_validates_messages_of_validates_length_of
	_validates_length_of(*attrs)
      end
    end
  end
end


module ActionView
  module Helpers
    module ActiveRecordHelper
      module L10n
	# Separate namespace for textdomain
	include GetText
	extend GetText
	module_function
	def error_messages_for(object, klass, options = {})
	  textdomain("rails")
	  options = options.symbolize_keys
  
	  unless object.errors.empty?
	    count = object.errors.count
	    record = ActiveRecord::Base.human_attribute_name(object.class.to_s)
	    klass.content_tag("div",
			klass.content_tag(
				    options[:header_tag] || "h2",
					  n_("%{num} error prohibited this %{record} from being saved", 
					     "%{num} errors prohibited this %{record} from being saved", count) %
					  {:num => count, :record => record}) +
			klass.content_tag("p", n_("There were problems with the following field:", 
					    "There were problems with the following fields:", count)) +
			klass.content_tag("ul", object.errors.full_messages.collect { |msg| klass.content_tag("li", msg) }),
			"id" => options[:id] || "errorExplanation", "class" => options[:class] || "errorExplanation"
			)
	  end
	end
      end
      def error_messages_for(object_name, options = {})
	object = instance_variable_get("@#{object_name}")
	L10n.error_messages_for(object, self, options)
      end
    end
  end
end

Rails::Info.property("GetText version") do 
  GetText::VERSION 
end