File: tk/msgcat.rb

Overview
Module Structure
Class Hierarchy
Code

Overview

Module Structure

  module: <Toplevel Module>
  class: TkMsgCatalog#8
extends
  Tk   
includes
  TkCore   
inherits from
  TkObject   
has properties
constant: TkCommandNames #13
constant: PACKAGE_NAME #26
class method: package_name #27
constant: MSGCAT_EXT #37
constant: UNKNOWN_CBTBL #39
class method: callback / 4 #58
method: initialize / 1 #92
attribute: msgcat_ext [RW] #104
method: method_missing / 2 #106
class method: translate (1/2) / 1 #144
class alias: mc (1/2) translate #151
class alias: [] (1/2) translate #152
method: translate (2/E) / 1 #154
alias: mc (2/E) translate #161
alias: [] (2/E) translate #162
class method: maxlen (1/2) / 1 #164
method: maxlen (2/E) / 1 #167
class method: locale (1/2) #171
method: locale (2/E) #174
class method: locale= (1/2) / 1 #178
method: locale= (2/E) / 1 #181
class method: preferences (1/2) #185
method: preferences (2/E) #188
class method: load_tk (1/2) / 1 #192
class method: load_rb (1/2) / 1 #196
method: load_tk (2/E) / 1 #208
method: load_rb (2/E) / 1 #212
class method: load (1/2) / 1 #224
alias: load (2/E) load_rb #227
class method: set_translation (1/2) / 4 #229
method: set_translation (2/E) / 4 #242
class method: set_translation_list (1/2) / 3 #259
method: set_translation_list (2/E) / 3 #272
class method: def_unknown_proc (1/2) / 1 #288
method: def_unknown_proc (2/E) / 1 #291

Class Hierarchy

Object ( Builtin-Module )
TkKernel
TkObject
  TkMsgCatalog    #8

Code

   1  #
   2  #   tk/msgcat.rb : methods for Tcl message catalog
   3  #                     by Hidetoshi Nagai <nagai@ai.kyutech.ac.jp>
   4  #
   5  require 'tk'
   6 
   7  #class TkMsgCatalog
   8  class TkMsgCatalog < TkObject
   9    include TkCore
  10    extend Tk
  11    #extend TkMsgCatalog
  12 
  13    TkCommandNames = [
  14      '::msgcat::mc'.freeze, 
  15      '::msgcat::mcmax'.freeze, 
  16      '::msgcat::mclocale'.freeze, 
  17      '::msgcat::mcpreferences'.freeze, 
  18      '::msgcat::mcload'.freeze, 
  19      '::msgcat::mcset'.freeze, 
  20      '::msgcat::mcmset'.freeze, 
  21      '::msgcat::mcunknown'.freeze
  22    ].freeze
  23 
  24    tk_call_without_enc('package', 'require', 'Tcl', '8.2')
  25 
  26    PACKAGE_NAME = 'msgcat'.freeze
  27    def self.package_name
  28      PACKAGE_NAME
  29    end
  30 
  31    if self.const_defined? :FORCE_VERSION
  32      tk_call_without_enc('package', 'require', 'msgcat', FORCE_VERSION)
  33    else
  34      tk_call_without_enc('package', 'require', 'msgcat')
  35    end
  36 
  37    MSGCAT_EXT = '.msg'
  38 
  39    UNKNOWN_CBTBL = Hash.new{|hash,key| hash[key] = {}}.taint
  40 
  41    TkCore::INTERP.add_tk_procs('::msgcat::mcunknown', 'args', <<-'EOL')
  42      if {[set st [catch {eval {ruby_cmd TkMsgCatalog callback} [namespace current] $args} ret]] != 0} {
  43         #return -code $st $ret
  44         set idx [string first "\n\n" $ret]
  45         if {$idx > 0} {
  46            return -code $st \
  47                   -errorinfo [string range $ret [expr $idx + 2] \
  48                                                 [string length $ret]] \
  49                   [string range $ret 0 [expr $idx - 1]]
  50         } else {
  51            return -code $st $ret
  52         }
  53      } else {
  54          return $ret
  55      }
  56    EOL
  57 
  58    def self.callback(namespace, locale, src_str, *args)
  59      src_str = sprintf(src_str, *args) unless args.empty?
  60      cmd_tbl = TkMsgCatalog::UNKNOWN_CBTBL[TkCore::INTERP.__getip]
  61      cmd = cmd_tbl[namespace]
  62      cmd = cmd_tbl['::'] unless cmd  # use global scope as interp default
  63      return src_str unless cmd       # no cmd -> return src-str (default action)
  64      begin
  65        cmd.call(locale, src_str)
  66      rescue SystemExit
  67        exit(0)
  68      rescue Interrupt
  69        exit!(1)
  70      rescue Exception => e
  71        begin
  72          msg = _toUTF8(e.class.inspect) + ': ' + 
  73                _toUTF8(e.message) + "\n" + 
  74                "\n---< backtrace of Ruby side >-----\n" + 
  75                _toUTF8(e.backtrace.join("\n")) + 
  76                "\n---< backtrace of Tk side >-------"
  77          if TkCore::WITH_ENCODING
  78            msg.force_encoding('utf-8')
  79          else
  80            msg.instance_variable_set(:@encoding, 'utf-8')
  81          end
  82        rescue Exception
  83          msg = e.class.inspect + ': ' + e.message + "\n" + 
  84                "\n---< backtrace of Ruby side >-----\n" + 
  85                e.backtrace.join("\n") + 
  86                "\n---< backtrace of Tk side >-------"
  87        end
  88        fail(e, msg)
  89      end
  90    end
  91 
  92    def initialize(namespace = nil)
  93      if namespace.kind_of?(TkNamespace)
  94        @namespace = namespace
  95      elsif namespace == nil
  96        @namespace = TkNamespace.new('::')  # global namespace
  97      else
  98        @namespace = TkNamespace.new(namespace)
  99      end
 100      @path = @namespace.path
 101 
 102      @msgcat_ext = '.msg'
 103    end
 104    attr_accessor :msgcat_ext
 105 
 106    def method_missing(id, *args)
 107      # locale(src, trans) ==> set_translation(locale, src, trans)
 108      loc = id.id2name
 109      case args.length
 110      when 0 # set locale
 111        self.locale=(loc)
 112 
 113      when 1 # src only, or trans_list
 114        if args[0].kind_of?(Array)
 115          # trans_list
 116          #list = args[0].collect{|src, trans|
 117          #  [ Tk::UTF8_String.new(src), Tk::UTF8_String.new(trans) ]
 118          #}
 119          self.set_translation_list(loc, args[0])
 120        else
 121          # src
 122          #self.set_translation(loc, Tk::UTF8_String.new(args[0]))
 123          self.set_translation(loc, args[0])
 124        end
 125 
 126      when 2 # src and trans, or, trans_list and enc
 127        if args[0].kind_of?(Array)
 128        else
 129          #self.set_translation(loc, args[0], Tk::UTF8_String.new(args[1]))
 130          self.set_translation(loc, *args)
 131        end
 132 
 133      when 3 # src and trans and enc
 134        self.set_translation(loc, *args)
 135 
 136      else
 137        super(id, *args)
 138  #      fail NameError, "undefined method `#{name}' for #{self.to_s}", error_at
 139 
 140      end
 141    end
 142 
 143    # *args ::= form, arg, arg, ...
 144    def self.translate(*args)
 145      dst = args.collect{|src|
 146        tk_call_without_enc('::msgcat::mc', _get_eval_string(src, true))
 147      }
 148      Tk.UTF8_String(sprintf(*dst))
 149    end
 150    class << self
 151      alias mc translate
 152      alias [] translate
 153    end
 154    def translate(*args)
 155      dst = args.collect{|src|
 156        @namespace.eval{tk_call_without_enc('::msgcat::mc', 
 157                                            _get_eval_string(src, true))}
 158      }
 159      Tk.UTF8_String(sprintf(*dst))
 160    end
 161    alias mc translate
 162    alias [] translate
 163 
 164    def self.maxlen(*src_strings)
 165      tk_call('::msgcat::mcmax', *src_strings).to_i
 166    end
 167    def maxlen(*src_strings)
 168      @namespace.eval{tk_call('::msgcat::mcmax', *src_strings).to_i}
 169    end
 170 
 171    def self.locale
 172      tk_call('::msgcat::mclocale')
 173    end
 174    def locale
 175      @namespace.eval{tk_call('::msgcat::mclocale')}
 176    end
 177 
 178    def self.locale=(locale)
 179      tk_call('::msgcat::mclocale', locale)
 180    end
 181    def locale=(locale)
 182      @namespace.eval{tk_call('::msgcat::mclocale', locale)}
 183    end
 184 
 185    def self.preferences
 186      tk_split_simplelist(tk_call('::msgcat::mcpreferences'))
 187    end
 188    def preferences
 189      tk_split_simplelist(@namespace.eval{tk_call('::msgcat::mcpreferences')})
 190    end
 191 
 192    def self.load_tk(dir)
 193      number(tk_call('::msgcat::mcload', dir))
 194    end
 195 
 196    def self.load_rb(dir)
 197      count = 0
 198      preferences().each{|loc|
 199        file = File.join(dir, loc + self::MSGCAT_EXT)
 200        if File.readable?(file)
 201          count += 1
 202          eval(open(file){|f| f.read})
 203        end
 204      }
 205      count
 206    end
 207 
 208    def load_tk(dir)
 209      number(@namespace.eval{tk_call('::msgcat::mcload', dir)})
 210    end
 211 
 212    def load_rb(dir)
 213      count = 0
 214      preferences().each{|loc|
 215        file = File.join(dir, loc + @msgcat_ext)
 216        if File.readable?(file)
 217          count += 1
 218          @namespace.eval(open(file){|f| f.read})
 219        end
 220      }
 221      count
 222    end
 223 
 224    def self.load(dir)
 225      self.load_rb(dir)
 226    end
 227    alias load load_rb
 228 
 229    def self.set_translation(locale, src_str, trans_str=None, enc='utf-8')
 230      if trans_str && trans_str != None
 231        trans_str = Tk.UTF8_String(_toUTF8(trans_str, enc))
 232        Tk.UTF8_String(tk_call_without_enc('::msgcat::mcset', 
 233                                           locale, 
 234                                           _get_eval_string(src_str, true), 
 235                                           trans_str))
 236      else
 237        Tk.UTF8_String(tk_call_without_enc('::msgcat::mcset', 
 238                                           locale, 
 239                                           _get_eval_string(src_str, true)))
 240      end
 241    end
 242    def set_translation(locale, src_str, trans_str=None, enc='utf-8')
 243      if trans_str && trans_str != None
 244        trans_str = Tk.UTF8_String(_toUTF8(trans_str, enc)) 
 245        Tk.UTF8_String(@namespace.eval{
 246                         tk_call_without_enc('::msgcat::mcset', 
 247                                             locale, 
 248                                             _get_eval_string(src_str, true), 
 249                                             trans_str)
 250                       })
 251      else
 252        Tk.UTF8_String(@namespace.eval{
 253                         tk_call_without_enc('::msgcat::mcset', 
 254                                             locale, 
 255                                             _get_eval_string(src_str, true))})
 256      end
 257    end
 258 
 259    def self.set_translation_list(locale, trans_list, enc='utf-8')
 260      # trans_list ::= [ [src, trans], [src, trans], ... ]
 261      list = []
 262      trans_list.each{|src, trans|
 263        if trans && trans != None
 264          list << _get_eval_string(src, true) 
 265          list << Tk.UTF8_Stirng(_toUTF8(trans, enc))
 266        else
 267          list << _get_eval_string(src, true) << ''
 268        end
 269      }
 270      number(tk_call_without_enc('::msgcat::mcmset', locale, list))
 271    end
 272    def set_translation_list(locale, trans_list, enc='utf-8')
 273      # trans_list ::= [ [src, trans], [src, trans], ... ]
 274      list = []
 275      trans_list.each{|src, trans|
 276        if trans && trans != None
 277          list << _get_eval_string(src, true) 
 278          list << Tk.UTF8_String(_toUTF8(trans, enc))
 279        else
 280          list << _get_eval_string(src, true) << ''
 281        end
 282      }
 283      number(@namespace.eval{
 284               tk_call_without_enc('::msgcat::mcmset', locale, list)
 285             })
 286    end
 287 
 288    def self.def_unknown_proc(cmd=Proc.new)
 289      TkMsgCatalog::UNKNOWN_CBTBL[TkCore::INTERP.__getip]['::'] = cmd
 290    end
 291    def def_unknown_proc(cmd=Proc.new)
 292      TkMsgCatalog::UNKNOWN_CBTBL[TkCore::INTERP.__getip][@namespace.path] = cmd
 293    end
 294  end
 295 
 296  TkMsgCat = TkMsgCatalog