summaryrefslogtreecommitdiff
path: root/lib/rbot/language.rb
blob: c9130ee0acc54c7b6c7904b167acc2ca3ea05814 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
#-- vim:sw=2:et
#++
#
# :title: Language module for rbot
#
# This module takes care of language handling for rbot:
# setting the core.language value, loading the appropriate
# .lang file etc.

module Irc
module Language

  # This constant hash holds the mapping
  # from long language names to the usual POSIX
  # locale specifications
  Lang2Locale = {
    :english  => 'en',
    :british_english  => 'en_GB',
    :american_english  => 'en_US',
    :italian  => 'it',
    :french   => 'fr',
    :german   => 'de',
    :dutch    => 'nl',
    :japanese => 'ja',
    :russian  => 'ru',
    :traditional_chinese => 'zh_TW',
    :simplified_chinese => 'zh_CN'
  }

  # Return the shortest language for the current
  # GetText locale
  def Language.from_locale
    lang = locale.language
    if locale.country
      str = lang + "_#{locale.country}"
      if Lang2Locale.value?(str)
        # Get the shortest key in Lang2Locale which maps to the given lang_country
        return Lang2Locale.select { |k, v| v == str }.transpose.first.map { |v| v.to_s }.sort { |a, b| a.length <=> b.length }.first
      end
    end
    # lang_country didn't work, let's try lan
    if Lang2Locale.value?(lang)
      # Get the shortest key in Lang2Locale which maps to the given lang
      return Lang2Locale.select { |k, v| v == lang }.transpose.first.map { |v| v.to_s }.sort { |a, b| a.length <=> b.length }.first
    end
    # all else fail, return 'english'
    return 'english'
  end

  class Language
    BotConfig.register BotConfigEnumValue.new('core.language', 
      :default => Irc::Language.from_locale, :wizard => true,
      :values => Proc.new{|bot|
            Dir.new(Config::datadir + "/languages").collect {|f|
              f =~ /\.lang$/ ? f.gsub(/\.lang$/, "") : nil
            }.compact
          },   
      :on_change => Proc.new {|bot, v| bot.lang.set_language v},
      :desc => "Which language file the bot should use")
    
    def initialize(bot, language)
      @bot = bot
      set_language language
    end
    attr_reader :language

    def set_language(language)
      lang_str = language.to_s.downcase.gsub(/\s+/,'_')
      lang_sym = lang_str.intern
      if Lang2Locale.key?(lang_sym)
        setlocale(Lang2Locale[lang_sym])
        debug "locale set to #{locale}"
        rbot_gettext_debug
      else
        warning "Unable to set locale, unknown language #{language} (#{lang_str})"
      end

      file = Config::datadir + "/languages/#{lang_str}.lang"
      unless(FileTest.exist?(file))
        raise "no such language: #{lang_str} (no such file #{file})"
      end
      @language = lang_str
      @file = file
      scan
      return if @bot.plugins.nil?
      @bot.plugins.core_modules.each { |p|
        if p.respond_to?('set_language')
          p.set_language(@language)
        end
      }
      @bot.plugins.plugins.each { |p|
        if p.respond_to?('set_language')
          p.set_language(@language)
        end
      }
    end

    def scan
      @strings = Hash.new
      current_key = nil
      IO.foreach(@file) {|l|
        next if l =~ /^$/
        next if l =~ /^\s*#/
        if(l =~ /^(\S+):$/)
          @strings[$1] = Array.new
          current_key = $1
        elsif(l =~ /^\s*(.*)$/)
          @strings[current_key] << $1
        end
      }
    end

    def rescan
      scan
    end

    def get(key)
      if(@strings.has_key?(key))
        return @strings[key][rand(@strings[key].length)]
      else
        raise "undefined language key"
      end
    end

    def save
      File.open(@file, "w") {|file|
        @strings.each {|key,val|
          file.puts "#{key}:"
          val.each_value {|v|
            file.puts "   #{v}"
          }
        }
      }
    end
  end

end
end