#! ruby -Ks
# SimpleGetText.rb .. [ruby-list:35459] Extreme Simple GetText for ruby
# SimpleGetText.pi
# copyleft (2002) take_tk
#
# TODO: 読み込みエラーのときに上書きしてしまう。
# TODO: ライブラリごとのデータファイルの指定。
#
# 2004-11-12(金): ver.0.1.5 require "Languages" => "lang/Languages"
# 2002-11-06(水): ver.0.1.5 locale → lang
# 2002-10-22(火): ver.0.1.4 データファイルが同じディレクトリでもよい。localeディレクトリに移動する。
# 2002-10-10(木): ver.0.1.3 改行のある文字列はヒアドキュメントで保存する。
# 2002-10-06(日): ver.0.1.2 EUC のデータに対応。
# 2002-10-02(水): ver.0.1.1 initial public version.

require "lang/Languages"

class SimpleGetText
  @@read_error = false
  @@src_locale = nil
  @@locale = nil #  "ja_JP.eucJP" "ja_JP.sjis" etc
  @@code = nil   #  EUC, SJIS, UTF
  @@lang = nil   # ja, en etc.
  @@package = nil
  @@locale_file = nil
  @@const_name = nil
  @@dst_hash = {}  
  @@dst_hash_changed = false
  @@no_conv = false
  @@auto_add = true
  @@prepared = nil

  def self.no_conv
    @@no_conv
  end
  def self.no_conv=(v)
    @@no_conv=v
  end

  def self.make_data_path
    dir0 = File.expand_path(File.dirname($0))+ "/"
    dir1 = dir0 + "locale/"
    Dir.mkdir dir1 unless FileTest.directory? dir1
    path0 = dir0 + @@package + "_" + @@lang
    path1 = dir1 + @@package + "_" + @@lang
    File.rename(path0,path1) if (! FileTest.file? path1) && (FileTest.file? path0)
    return path1 if FileTest.file? path1
    return path0 if FileTest.file? path0
    return path1
  end

  def self.save(disp=$DEBUG)
    print "finalizer_callback: writing to #{@@locale_file} " if disp
    File.rename( @@locale_file , @@locale_file+"~" ) if FileTest.exist? @@locale_file
    File.open( @@locale_file , "w" ){|f|
      f.write( "class #{self.name}\n")
      f.write( "  "+@@const_name + " = {\n" )
      @@dst_hash.sort.each{|k,v|
        print "." if disp
        if (/.+\n.+/ =~ v) || v.size > 60
          f.puts(" #{k.inspect} => <<MMMM,")
          f.puts( v )
          f.puts("MMMM")
        else
          f.write(" #{k.inspect} => #{v.inspect},\n")
        end
      }
      f.write( "  }\nend\n")
    }
    print " done\n" if disp
  end

  def self.finalizer_callback
    proc{
      if @@dst_hash_changed
        save(true)
      end
    }
  end

  def self.prepare
    ##→C:/PROGRA~1/Apollo/lib/ruby/1.6/irb/locale.rb[String]
    ##@@locale = ENV["LC_MESSAGES"] || ENV["LC_ALL"] || ENV["LANG"]

    @@lang ||= Languages.ms_code_to_data[0] # "ja"
      p "dst_locale = #{@@lang}"        if $DEBUG
    
    @@package ||= File.basename($0.tr("\\","/"))
      p "package = #{@@package}"        if $DEBUG 

    @@locale_file = make_data_path
      p "locale file = #{@locale_file}" if $DEBUG

    @@const_name = @@lang.upcase
      p "const name = #{@const_name}"   if $DEBUG

    @@dst_hash = {}
    begin
      #
      # if error occurs here
      # please edit @locale_file, which may have bug.
      # '$DEBUG = true' or 'ruby -d' shows @@locale_file. 
      #
     load @@locale_file if FileTest.file? @@locale_file
    rescue Exception
      puts "error on load file #{@@locale_file}."
      raise
    end
    begin
      @@dst_hash = eval(self.name+"::"+@@const_name)
    rescue Exception
    end
    @@dst_hash = {} unless @@dst_hash.is_a? Hash
      p "#{@@const_name} = #{@@dst_hash.inspect}"  if $DEBUG

    if $KCODE
      @@dst_hash = convert( @@dst_hash )
    end

    @@prepared = ""
      p "prepared"  if $DEBUG
    callback = self.finalizer_callback
    ObjectSpace.define_finalizer(@@prepared, callback)
  end
  
  def self.convert( hash )
    return hash if $KCODE.empty? || $KCODE.upcase[0,1] == "N"
    require "kconv"
      p "$KCODE = #{$KCODE.inspect}" if $DEBUG # SJIS
    conv = nil
    case $KCODE.upcase[0,1]
    when "S" ; conv = Kconv::SJIS
    when "E" ; conv = Kconv::EUC
    end
    if conv
      ret = {}
      hash.each{|k,v| ret[k]=Kconv::kconv(v,conv)}
      hash = ret
    end
    return hash
  end
  
  def self.lang=(v)
    @@lang = v.downcase
    self.prepare
  end
  def self.lang
    @@lang
  end
  # alias.. do not use
  def self.locale=(v)
    self.lang = v
  end
  def self.locale
    @@lang
  end
  
  def self.package=(v)
    @@package = v
    self.prepare
  end
  def self.package
    @@package
  end
  
  def self.get_caller(caller)
  end
  
  def self.get_text( str )
    return str if @@no_conv
    self.prepare  unless @@prepared
    ret = @@dst_hash[str]
    return ret if ret 
    unless @@auto_add
      raise "'#{str}' => '#{str}' not defined in #{@@locale_file}"
    else
      @@dst_hash[str] = str
      @@dst_hash_changed = true
    end
    return str
  end

end

class String
  def get_text
    SimpleGetText.get_text( self )
  end
  alias _ get_text
end

########

if __FILE__ == $0

##$DEBUG = true

#SimpleGetText.lang = "ja"
#SimpleGetText.lang = "en"
SimpleGetText.lang = "de"

  p "bonjour"._
  p "bye"._
  p "じゃね！"._

msg =<<MMMM._
  改行のあるメッセージの場合、
  ヒアドキュメントで保存する。
MMMM

puts msg

raise

end
